mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
Merge branch 'devel' of github.com:Araq/Nimrod into devel
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2013 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
@@ -291,6 +291,8 @@ const
|
||||
|
||||
sfNoRoot* = sfBorrow # a local variable is provably no root so it doesn't
|
||||
# require RC ops
|
||||
sfCompileToCpp* = sfInfixCall # compile the module as C++ code
|
||||
sfCompileToObjc* = sfNamedParamCall # compile the module as Objective-C code
|
||||
|
||||
const
|
||||
# getting ready for the future expr/stmt merge
|
||||
@@ -476,7 +478,7 @@ type
|
||||
# and first phase symbol lookup in generics
|
||||
skConditional, # symbol for the preprocessor (may become obsolete)
|
||||
skDynLib, # symbol represents a dynamic library; this is used
|
||||
# internally; it does not exist in Nimrod code
|
||||
# internally; it does not exist in Nim code
|
||||
skParam, # a parameter
|
||||
skGenericParam, # a generic parameter; eq in ``proc x[eq=`==`]()``
|
||||
skTemp, # a temporary variable (introduced by compiler)
|
||||
@@ -501,7 +503,8 @@ type
|
||||
skStub, # symbol is a stub and not yet loaded from the ROD
|
||||
# file (it is loaded on demand, which may
|
||||
# mean: never)
|
||||
skPackage # symbol is a package (used for canonicalization)
|
||||
skPackage, # symbol is a package (used for canonicalization)
|
||||
skAlias # an alias (needs to be resolved immediately)
|
||||
TSymKinds* = set[TSymKind]
|
||||
|
||||
const
|
||||
@@ -678,7 +681,7 @@ type
|
||||
heapRoot*: PRope # keeps track of the enclosing heap object that
|
||||
# owns this location (required by GC algorithms
|
||||
# employing heap snapshots or sliding views)
|
||||
a*: int # location's "address", i.e. slot for temporaries
|
||||
a*: int
|
||||
|
||||
# ---------------- end of backend information ------------------------------
|
||||
|
||||
@@ -731,8 +734,9 @@ type
|
||||
# check for the owner when touching 'usedGenerics'.
|
||||
usedGenerics*: seq[PInstantiation]
|
||||
tab*: TStrTable # interface table for modules
|
||||
of skLet, skVar, skField:
|
||||
guard*: PSym
|
||||
else: nil
|
||||
|
||||
magic*: TMagic
|
||||
typ*: PType
|
||||
name*: PIdent
|
||||
@@ -872,7 +876,7 @@ const
|
||||
tyProc, tyString, tyError}
|
||||
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
|
||||
skIterator, skClosureIterator,
|
||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
|
||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
||||
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
||||
nfDotSetter, nfDotField,
|
||||
nfIsRef}
|
||||
@@ -1162,7 +1166,6 @@ proc newProcNode*(kind: TNodeKind, info: TLineInfo, body: PNode,
|
||||
result.sons = @[name, pattern, genericParams, params,
|
||||
pragmas, exceptions, body]
|
||||
|
||||
|
||||
proc newType(kind: TTypeKind, owner: PSym): PType =
|
||||
new(result)
|
||||
result.kind = kind
|
||||
@@ -1172,8 +1175,8 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
|
||||
result.id = getID()
|
||||
when debugIds:
|
||||
registerId(result)
|
||||
#if result.id < 2000 then
|
||||
# MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
||||
#if result.id < 2000:
|
||||
# messageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
|
||||
|
||||
proc mergeLoc(a: var TLoc, b: TLoc) =
|
||||
if a.k == low(a.k): a.k = b.k
|
||||
@@ -1229,6 +1232,8 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
|
||||
result.position = s.position
|
||||
result.loc = s.loc
|
||||
result.annex = s.annex # BUGFIX
|
||||
if result.kind in {skVar, skLet, skField}:
|
||||
result.guard = s.guard
|
||||
|
||||
proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo): PSym =
|
||||
result = newSym(s.kind, newIdent, s.owner, info)
|
||||
|
||||
@@ -832,7 +832,14 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
|
||||
discard cgsym(p.module, "E_Base")
|
||||
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
|
||||
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||
if isDefined("nimStdSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||
elif isDefined("nimSigSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
|
||||
elif isDefined("nimRawSetjmp"):
|
||||
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
|
||||
else:
|
||||
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
|
||||
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
|
||||
var length = sonsLen(t)
|
||||
add(p.nestedTryStmts, t)
|
||||
|
||||
@@ -13,7 +13,7 @@ import
|
||||
ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp,
|
||||
options, intsets,
|
||||
nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os,
|
||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
|
||||
times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, condsyms,
|
||||
rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases, lowerings,
|
||||
semparallel
|
||||
|
||||
|
||||
@@ -80,9 +80,9 @@ proc writeVersionInfo(pass: TCmdLinePass) =
|
||||
platform.OS[platform.hostOS].name,
|
||||
CPU[platform.hostCPU].name]))
|
||||
|
||||
const gitHash = gorge("git log -n 1 --format=%H")
|
||||
discard """const gitHash = gorge("git log -n 1 --format=%H")
|
||||
if gitHash.strip.len == 40:
|
||||
msgWriteln("git hash: " & gitHash)
|
||||
msgWriteln("git hash: " & gitHash)"""
|
||||
|
||||
msgWriteln("active boot switches:" & usedRelease & usedAvoidTimeMachine &
|
||||
usedTinyC & usedGnuReadline & usedNativeStacktrace & usedNoCaas &
|
||||
@@ -393,7 +393,9 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||
of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
|
||||
of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
|
||||
of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
|
||||
of "threads": processOnOffSwitchG({optThreads}, arg, pass, info)
|
||||
of "threads":
|
||||
processOnOffSwitchG({optThreads}, arg, pass, info)
|
||||
if optThreads in gGlobalOptions: incl(gNotes, warnGcUnsafe)
|
||||
of "tlsemulation": processOnOffSwitchG({optTlsEmulation}, arg, pass, info)
|
||||
of "taintmode": processOnOffSwitchG({optTaintMode}, arg, pass, info)
|
||||
of "implicitstatic":
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
@@ -60,7 +60,7 @@ const
|
||||
quick
|
||||
release debug
|
||||
useWinAnsi useFork useNimRtl useMalloc useRealtimeGC ssl memProfiler
|
||||
nodejs kwin
|
||||
nodejs kwin nimfix
|
||||
|
||||
usesysassert usegcassert tinyC useFFI
|
||||
useStdoutAsStdmsg createNimRtl
|
||||
@@ -69,6 +69,8 @@ const
|
||||
reportMissedDeadlines avoidTimeMachine useClone ignoreAllocationSize
|
||||
debugExecProcesses pcreDll useLipzipSrc
|
||||
preventDeadlocks UNICODE winUnicode trackGcHeaders posixRealtime
|
||||
|
||||
nimStdSetjmp nimRawSetjmp nimSigSetjmp
|
||||
""".split
|
||||
|
||||
proc initDefines*() =
|
||||
@@ -85,6 +87,7 @@ proc initDefines*() =
|
||||
defineSymbol("nimnewshared")
|
||||
defineSymbol("nimrequiresnimframe")
|
||||
defineSymbol("nimparsebiggestfloatmagic")
|
||||
defineSymbol("nimalias")
|
||||
|
||||
# add platform specific symbols:
|
||||
for c in low(CPU)..high(CPU):
|
||||
@@ -136,3 +139,7 @@ proc initDefines*() =
|
||||
declareSymbol("emulatedthreadvars")
|
||||
if platform.OS[targetOS].props.contains(ospLacksThreadVars):
|
||||
defineSymbol("emulatedthreadvars")
|
||||
case targetOS
|
||||
of osSolaris, osNetbsd, osFreebsd, osOpenbsd, osMacosx:
|
||||
defineSymbol("nimRawSetjmp")
|
||||
else: discard
|
||||
|
||||
@@ -383,6 +383,8 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||
var seeSrcRope: PRope = nil
|
||||
let docItemSeeSrc = getConfigVar("doc.item.seesrc")
|
||||
if docItemSeeSrc.len > 0 and options.docSeeSrcUrl.len > 0:
|
||||
# XXX toFilename doesn't really work. We need to ensure that this keeps
|
||||
# returning a relative path.
|
||||
let urlRope = ropeFormatNamedVars(options.docSeeSrcUrl,
|
||||
["path", "line"], [n.info.toFilename.toRope, toRope($n.info.line)])
|
||||
dispA(seeSrcRope, "$1", "", [ropeFormatNamedVars(docItemSeeSrc,
|
||||
|
||||
@@ -92,7 +92,7 @@ proc rawImportSymbol(c: PContext, s: PSym) =
|
||||
if s.kind == skConverter: addConverter(c, s)
|
||||
if hasPattern(s): addPattern(c, s)
|
||||
|
||||
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
|
||||
let ident = lookups.considerQuotedIdent(n)
|
||||
let s = strTableGet(fromMod.tab, ident)
|
||||
if s == nil:
|
||||
@@ -155,10 +155,12 @@ proc importModuleAs(n: PNode, realModule: PSym): PSym =
|
||||
# some misguided guy will write 'import abc.foo as foo' ...
|
||||
result = createModuleAlias(realModule, n.sons[1].ident, n.sons[1].info)
|
||||
|
||||
proc myImportModule(c: PContext, n: PNode): PSym =
|
||||
proc myImportModule(c: PContext, n: PNode): PSym =
|
||||
var f = checkModuleName(n)
|
||||
if f != InvalidFileIDX:
|
||||
result = importModuleAs(n, gImportModule(c.module, f))
|
||||
if result.info.fileIndex == n.info.fileIndex:
|
||||
localError(n.info, errGenerated, "A module cannot import itself")
|
||||
if sfDeprecated in result.flags:
|
||||
message(n.info, warnDeprecated, result.name.s)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2012 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, idents, semdata, types, msgs, options, rodread,
|
||||
renderer, wordrecg, idgen
|
||||
renderer, wordrecg, idgen, nimfix.prettybase
|
||||
|
||||
proc ensureNoMissingOrUnusedSymbols(scope: PScope)
|
||||
|
||||
@@ -40,11 +40,8 @@ proc considerQuotedIdent*(n: PNode): PIdent =
|
||||
template addSym*(scope: PScope, s: PSym) =
|
||||
strTableAdd(scope.symbols, s)
|
||||
|
||||
proc addUniqueSym*(scope: PScope, s: PSym): TResult =
|
||||
if strTableIncl(scope.symbols, s):
|
||||
result = Failure
|
||||
else:
|
||||
result = Success
|
||||
proc addUniqueSym*(scope: PScope, s: PSym): bool =
|
||||
result = not strTableIncl(scope.symbols, s)
|
||||
|
||||
proc openScope*(c: PContext): PScope {.discardable.} =
|
||||
result = PScope(parent: c.currentScope,
|
||||
@@ -65,6 +62,17 @@ iterator walkScopes*(scope: PScope): PScope =
|
||||
yield current
|
||||
current = current.parent
|
||||
|
||||
proc skipAlias*(s: PSym; n: PNode): PSym =
|
||||
if s == nil or s.kind != skAlias:
|
||||
result = s
|
||||
else:
|
||||
result = s.owner
|
||||
if gCmd == cmdPretty:
|
||||
prettybase.replaceDeprecated(n.info, s, result)
|
||||
else:
|
||||
message(n.info, warnDeprecated, "use " & result.name.s & " instead; " &
|
||||
s.name.s)
|
||||
|
||||
proc localSearchInScope*(c: PContext, s: PIdent): PSym =
|
||||
result = strTableGet(c.currentScope.symbols, s)
|
||||
|
||||
@@ -139,14 +147,14 @@ proc wrongRedefinition*(info: TLineInfo, s: string) =
|
||||
localError(info, errAttemptToRedefine, s)
|
||||
|
||||
proc addDecl*(c: PContext, sym: PSym) =
|
||||
if c.currentScope.addUniqueSym(sym) == Failure:
|
||||
if not c.currentScope.addUniqueSym(sym):
|
||||
wrongRedefinition(sym.info, sym.name.s)
|
||||
|
||||
proc addPrelimDecl*(c: PContext, sym: PSym) =
|
||||
discard c.currentScope.addUniqueSym(sym)
|
||||
|
||||
proc addDeclAt*(scope: PScope, sym: PSym) =
|
||||
if scope.addUniqueSym(sym) == Failure:
|
||||
if not scope.addUniqueSym(sym):
|
||||
wrongRedefinition(sym.info, sym.name.s)
|
||||
|
||||
proc addInterfaceDeclAux(c: PContext, sym: PSym) =
|
||||
@@ -163,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
|
||||
if fn.kind notin OverloadableSyms:
|
||||
internalError(fn.info, "addOverloadableSymAt")
|
||||
return
|
||||
var check = strTableGet(scope.symbols, fn.name)
|
||||
let check = strTableGet(scope.symbols, fn.name)
|
||||
if check != nil and check.kind notin OverloadableSyms:
|
||||
wrongRedefinition(fn.info, fn.name.s)
|
||||
else:
|
||||
@@ -179,20 +187,41 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
|
||||
addOverloadableSymAt(scope, sym)
|
||||
addInterfaceDeclAux(c, sym)
|
||||
|
||||
when defined(nimfix):
|
||||
import strutils
|
||||
|
||||
# when we cannot find the identifier, retry with a changed identifer:
|
||||
proc altSpelling(x: PIdent): PIdent =
|
||||
case x.s[0]
|
||||
of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
|
||||
of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
|
||||
else: result = x
|
||||
|
||||
template fixSpelling(n: PNode; ident: PIdent; op: expr) =
|
||||
let alt = ident.altSpelling
|
||||
result = op(c, alt).skipAlias(n)
|
||||
if result != nil:
|
||||
prettybase.replaceDeprecated(n.info, ident, alt)
|
||||
return result
|
||||
else:
|
||||
template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
|
||||
|
||||
proc lookUp*(c: PContext, n: PNode): PSym =
|
||||
# Looks up a symbol. Generates an error in case of nil.
|
||||
case n.kind
|
||||
of nkIdent:
|
||||
result = searchInScopes(c, n.ident)
|
||||
if result == nil:
|
||||
result = searchInScopes(c, n.ident).skipAlias(n)
|
||||
if result == nil:
|
||||
fixSpelling(n, n.ident, searchInScopes)
|
||||
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||
result = errorSym(c, n)
|
||||
of nkSym:
|
||||
result = n.sym
|
||||
of nkAccQuoted:
|
||||
var ident = considerQuotedIdent(n)
|
||||
result = searchInScopes(c, ident)
|
||||
result = searchInScopes(c, ident).skipAlias(n)
|
||||
if result == nil:
|
||||
fixSpelling(n, ident, searchInScopes)
|
||||
localError(n.info, errUndeclaredIdentifier, ident.s)
|
||||
result = errorSym(c, n)
|
||||
else:
|
||||
@@ -206,36 +235,38 @@ type
|
||||
TLookupFlag* = enum
|
||||
checkAmbiguity, checkUndeclared
|
||||
|
||||
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||
case n.kind
|
||||
of nkIdent, nkAccQuoted:
|
||||
var ident = considerQuotedIdent(n)
|
||||
result = searchInScopes(c, ident)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
result = searchInScopes(c, ident).skipAlias(n)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
fixSpelling(n, ident, searchInScopes)
|
||||
localError(n.info, errUndeclaredIdentifier, ident.s)
|
||||
result = errorSym(c, n)
|
||||
elif checkAmbiguity in flags and result != nil and
|
||||
contains(c.ambiguousSymbols, result.id):
|
||||
elif checkAmbiguity in flags and result != nil and
|
||||
contains(c.ambiguousSymbols, result.id):
|
||||
localError(n.info, errUseQualifier, ident.s)
|
||||
of nkSym:
|
||||
result = n.sym
|
||||
if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
|
||||
if checkAmbiguity in flags and contains(c.ambiguousSymbols, result.id):
|
||||
localError(n.info, errUseQualifier, n.sym.name.s)
|
||||
of nkDotExpr:
|
||||
of nkDotExpr:
|
||||
result = nil
|
||||
var m = qualifiedLookUp(c, n.sons[0], flags*{checkUndeclared})
|
||||
if (m != nil) and (m.kind == skModule):
|
||||
if m != nil and m.kind == skModule:
|
||||
var ident: PIdent = nil
|
||||
if n.sons[1].kind == nkIdent:
|
||||
if n.sons[1].kind == nkIdent:
|
||||
ident = n.sons[1].ident
|
||||
elif n.sons[1].kind == nkAccQuoted:
|
||||
elif n.sons[1].kind == nkAccQuoted:
|
||||
ident = considerQuotedIdent(n.sons[1])
|
||||
if ident != nil:
|
||||
if m == c.module:
|
||||
result = strTableGet(c.topLevelScope.symbols, ident)
|
||||
else:
|
||||
result = strTableGet(m.tab, ident)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
if ident != nil:
|
||||
if m == c.module:
|
||||
result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n)
|
||||
else:
|
||||
result = strTableGet(m.tab, ident).skipAlias(n)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
fixSpelling(n.sons[1], ident, searchInScopes)
|
||||
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
|
||||
result = errorSym(c, n.sons[1])
|
||||
elif n.sons[1].kind == nkSym:
|
||||
@@ -256,7 +287,7 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
o.scope = c.currentScope
|
||||
o.mode = oimNoQualifier
|
||||
while true:
|
||||
result = initIdentIter(o.it, o.scope.symbols, ident)
|
||||
result = initIdentIter(o.it, o.scope.symbols, ident).skipAlias(n)
|
||||
if result != nil:
|
||||
break
|
||||
else:
|
||||
@@ -277,11 +308,12 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
if ident != nil:
|
||||
if o.m == c.module:
|
||||
# a module may access its private members:
|
||||
result = initIdentIter(o.it, c.topLevelScope.symbols, ident)
|
||||
result = initIdentIter(o.it, c.topLevelScope.symbols,
|
||||
ident).skipAlias(n)
|
||||
o.mode = oimSelfModule
|
||||
else:
|
||||
result = initIdentIter(o.it, o.m.tab, ident)
|
||||
else:
|
||||
else:
|
||||
result = initIdentIter(o.it, o.m.tab, ident).skipAlias(n)
|
||||
else:
|
||||
localError(n.sons[1].info, errIdentifierExpected,
|
||||
renderTree(n.sons[1]))
|
||||
result = errorSym(c, n.sons[1])
|
||||
@@ -307,18 +339,18 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
result = nil
|
||||
of oimNoQualifier:
|
||||
if o.scope != nil:
|
||||
result = nextIdentIter(o.it, o.scope.symbols)
|
||||
result = nextIdentIter(o.it, o.scope.symbols).skipAlias(n)
|
||||
while result == nil:
|
||||
o.scope = o.scope.parent
|
||||
if o.scope == nil: break
|
||||
result = initIdentIter(o.it, o.scope.symbols, o.it.name)
|
||||
result = initIdentIter(o.it, o.scope.symbols, o.it.name).skipAlias(n)
|
||||
# BUGFIX: o.it.name <-> n.ident
|
||||
else:
|
||||
result = nil
|
||||
of oimSelfModule:
|
||||
result = nextIdentIter(o.it, c.topLevelScope.symbols)
|
||||
result = nextIdentIter(o.it, c.topLevelScope.symbols).skipAlias(n)
|
||||
of oimOtherModule:
|
||||
result = nextIdentIter(o.it, o.m.tab)
|
||||
result = nextIdentIter(o.it, o.m.tab).skipAlias(n)
|
||||
of oimSymChoice:
|
||||
if o.symChoiceIndex < sonsLen(n):
|
||||
result = n.sons[o.symChoiceIndex].sym
|
||||
@@ -329,31 +361,27 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
|
||||
o.mode = oimSymChoiceLocalLookup
|
||||
o.scope = c.currentScope
|
||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||
n.sons[0].sym.name, o.inSymChoice)
|
||||
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||
while result == nil:
|
||||
o.scope = o.scope.parent
|
||||
if o.scope == nil: break
|
||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||
n.sons[0].sym.name, o.inSymChoice)
|
||||
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||
of oimSymChoiceLocalLookup:
|
||||
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice)
|
||||
result = nextIdentExcluding(o.it, o.scope.symbols, o.inSymChoice).skipAlias(n)
|
||||
while result == nil:
|
||||
o.scope = o.scope.parent
|
||||
if o.scope == nil: break
|
||||
result = firstIdentExcluding(o.it, o.scope.symbols,
|
||||
n.sons[0].sym.name, o.inSymChoice)
|
||||
n.sons[0].sym.name, o.inSymChoice).skipAlias(n)
|
||||
|
||||
if result != nil and result.kind == skStub: loadStub(result)
|
||||
|
||||
when false:
|
||||
proc qualifiedLookUpPreferImmediate*(c: PContext, n: PNode,
|
||||
flags = {checkUndeclared}): PSym =
|
||||
var o: TOverloadIter
|
||||
result = initOverloadIter(o, c, n)
|
||||
var a = result
|
||||
while a != nil:
|
||||
if sfImmediate in a.flags: return a
|
||||
a = nextOverloadIter(o, c, n)
|
||||
if result == nil and checkUndeclared in flags:
|
||||
localError(n.info, errUndeclaredIdentifier, n.considerQuotedIdent.s)
|
||||
result = errorSym(c, n)
|
||||
proc pickSym*(c: PContext, n: PNode; kind: TSymKind;
|
||||
flags: TSymFlags = {}): PSym =
|
||||
var o: TOverloadIter
|
||||
var a = initOverloadIter(o, c, n)
|
||||
while a != nil:
|
||||
if a.kind == kind and flags <= a.flags:
|
||||
return a
|
||||
a = nextOverloadIter(o, c, n)
|
||||
|
||||
106
compiler/nimfix/nimfix.nim
Normal file
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]
|
||||
Name: "Nimrod"
|
||||
Version: "$version"
|
||||
@@ -34,11 +37,11 @@ Files: "config/nimdoc.cfg"
|
||||
Files: "config/nimdoc.tex.cfg"
|
||||
|
||||
[Documentation]
|
||||
Files: "doc/*.txt"
|
||||
Files: "doc/*.html"
|
||||
Files: "doc/*.cfg"
|
||||
Files: "doc/*.pdf"
|
||||
Files: "doc/*.ini"
|
||||
; Files: "doc/*.html"
|
||||
; Files: "doc/*.cfg"
|
||||
; Files: "doc/*.pdf"
|
||||
; Files: "doc/*.ini"
|
||||
Files: "doc/overview.html"
|
||||
Start: "doc/overview.html"
|
||||
|
||||
|
||||
@@ -61,13 +64,9 @@ Files: "compiler/readme.txt"
|
||||
Files: "compiler/nimrod.ini"
|
||||
Files: "compiler/nimrod.cfg"
|
||||
Files: "compiler/*.nim"
|
||||
Files: "compiler/c2nim/*.nim"
|
||||
Files: "compiler/c2nim/*.cfg"
|
||||
Files: "compiler/pas2nim/*.nim"
|
||||
Files: "compiler/pas2nim/*.cfg"
|
||||
|
||||
Files: "build/empty.txt"
|
||||
Files: "bin/empty.txt"
|
||||
Files: "doc/*.txt"
|
||||
Files: "compiler/nimfix/*.nim"
|
||||
Files: "compiler/nimfix/*.cfg"
|
||||
|
||||
|
||||
[Lib]
|
||||
@@ -115,17 +114,22 @@ Files: "examples/*.tmpl"
|
||||
|
||||
[Windows]
|
||||
Files: "bin/nimrod.exe"
|
||||
Files: "bin/nimrod_debug.exe"
|
||||
Files: "bin/c2nim.exe"
|
||||
Files: "bin/niminst.exe"
|
||||
Files: "bin/nimgrep.exe"
|
||||
|
||||
Files: "dist/*.dll"
|
||||
Files: "koch.exe"
|
||||
Files: "dist/mingw"
|
||||
; Files: "dist/mingw"
|
||||
Files: "start.bat"
|
||||
BinPath: r"bin;dist\mingw\bin;dist"
|
||||
InnoSetup: "Yes"
|
||||
|
||||
; Section | dir | zipFile | size hint (in KB) | url | exe start menu entry
|
||||
Download: r"Documentation|doc|docs.zip|13824|http://nim-lang.org/download/docs-${version}.zip"
|
||||
Download: r"C Compiler (MingW)|dist|mingw.zip|82944|http://nim-lang.org/download/${mingw}.zip"
|
||||
Download: r"Aporia IDE|dist|aporia.zip|97997|http://nim-lang.org/download/aporia-0.1.3.zip|aporia\bin\aporia.exe"
|
||||
; for now only NSIS supports optional downloads
|
||||
|
||||
[UnixBin]
|
||||
Files: "bin/nimrod"
|
||||
@@ -140,6 +144,9 @@ UninstallScript: "yes"
|
||||
path = r"c:\Program Files (x86)\Inno Setup 5\iscc.exe"
|
||||
flags = "/Q"
|
||||
|
||||
[NSIS]
|
||||
path = r"c:\Program Files (x86)\NSIS\makensis.exe"
|
||||
flags = "/V0"
|
||||
|
||||
[C_Compiler]
|
||||
path = r""
|
||||
|
||||
@@ -14,7 +14,7 @@ const
|
||||
MaxSetElements* = 1 shl 16 # (2^16) to support unicode character sets?
|
||||
VersionMajor* = 0
|
||||
VersionMinor* = 9
|
||||
VersionPatch* = 5
|
||||
VersionPatch* = 6
|
||||
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch
|
||||
|
||||
RodFileVersion* = "1215" # modify this if the rod-format changes!
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#
|
||||
#
|
||||
# The Nimrod Compiler
|
||||
# The Nim Compiler
|
||||
# (c) Copyright 2014 Andreas Rumpf
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
@@ -24,7 +24,7 @@ const
|
||||
wCompilerproc, wProcVar, wDeprecated, wVarargs, wCompileTime, wMerge,
|
||||
wBorrow, wExtern, wImportCompilerProc, wThread, wImportCpp, wImportObjC,
|
||||
wAsmNoStackFrame, wError, wDiscardable, wNoInit, wDestructor, wCodegenDecl,
|
||||
wGensym, wInject, wRaises, wTags, wUses, wOperator, wDelegator, wGcSafe,
|
||||
wGensym, wInject, wRaises, wTags, wLocks, wDelegator, wGcSafe,
|
||||
wOverride}
|
||||
converterPragmas* = procPragmas
|
||||
methodPragmas* = procPragmas
|
||||
@@ -36,8 +36,8 @@ const
|
||||
iteratorPragmas* = {FirstCallConv..LastCallConv, wNosideeffect, wSideeffect,
|
||||
wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wDiscardable, wGensym, wInject, wRaises,
|
||||
wTags, wUses, wOperator, wGcSafe}
|
||||
exprPragmas* = {wLine}
|
||||
wTags, wLocks, wGcSafe}
|
||||
exprPragmas* = {wLine, wLocks}
|
||||
stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
|
||||
wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
|
||||
wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
|
||||
@@ -45,27 +45,27 @@ const
|
||||
wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
|
||||
wFloatchecks, wInfChecks, wNanChecks, wPragma, wEmit, wUnroll,
|
||||
wLinearScanEnd, wPatterns, wEffects, wNoForward, wComputedGoto,
|
||||
wInjectStmt}
|
||||
wInjectStmt, wDeprecated}
|
||||
lambdaPragmas* = {FirstCallConv..LastCallConv, wImportc, wExportc, wNodecl,
|
||||
wNosideeffect, wSideeffect, wNoreturn, wDynlib, wHeader,
|
||||
wDeprecated, wExtern, wThread, wImportCpp, wImportObjC, wAsmNoStackFrame,
|
||||
wRaises, wUses, wTags, wGcSafe}
|
||||
wRaises, wLocks, wTags, wGcSafe}
|
||||
typePragmas* = {wImportc, wExportc, wDeprecated, wMagic, wAcyclic, wNodecl,
|
||||
wPure, wHeader, wCompilerproc, wFinal, wSize, wExtern, wShallow,
|
||||
wImportCpp, wImportObjC, wError, wIncompleteStruct, wByCopy, wByRef,
|
||||
wInheritable, wGensym, wInject, wRequiresInit, wUnchecked, wUnion, wPacked,
|
||||
wBorrow, wGcSafe}
|
||||
fieldPragmas* = {wImportc, wExportc, wDeprecated, wExtern,
|
||||
wImportCpp, wImportObjC, wError}
|
||||
wImportCpp, wImportObjC, wError, wGuard}
|
||||
varPragmas* = {wImportc, wExportc, wVolatile, wRegister, wThreadVar, wNodecl,
|
||||
wMagic, wHeader, wDeprecated, wCompilerproc, wDynlib, wExtern,
|
||||
wImportCpp, wImportObjC, wError, wNoInit, wCompileTime, wGlobal,
|
||||
wGensym, wInject, wCodegenDecl}
|
||||
wGensym, wInject, wCodegenDecl, wGuard}
|
||||
constPragmas* = {wImportc, wExportc, wHeader, wDeprecated, wMagic, wNodecl,
|
||||
wExtern, wImportCpp, wImportObjC, wError, wGensym, wInject}
|
||||
letPragmas* = varPragmas
|
||||
procTypePragmas* = {FirstCallConv..LastCallConv, wVarargs, wNosideeffect,
|
||||
wThread, wRaises, wUses, wTags, wGcSafe}
|
||||
wThread, wRaises, wLocks, wTags, wGcSafe}
|
||||
allRoutinePragmas* = procPragmas + iteratorPragmas + lambdaPragmas
|
||||
|
||||
proc pragma*(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords)
|
||||
@@ -128,12 +128,16 @@ proc processImportCpp(s: PSym, extname: string) =
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfInfixCall)
|
||||
excl(s.flags, sfForward)
|
||||
let m = s.getModule()
|
||||
incl(m.flags, sfCompileToCpp)
|
||||
|
||||
proc processImportObjC(s: PSym, extname: string) =
|
||||
setExternName(s, extname)
|
||||
incl(s.flags, sfImportc)
|
||||
incl(s.flags, sfNamedParamCall)
|
||||
excl(s.flags, sfForward)
|
||||
let m = s.getModule()
|
||||
incl(m.flags, sfCompileToObjC)
|
||||
|
||||
proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
|
||||
result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
|
||||
@@ -514,27 +518,6 @@ proc pragmaRaisesOrTags(c: PContext, n: PNode) =
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc pragmaUses(c: PContext, n: PNode) =
|
||||
proc processExc(c: PContext, x: PNode): PNode =
|
||||
if x.kind in {nkAccQuoted, nkIdent, nkSym,
|
||||
nkOpenSymChoice, nkClosedSymChoice}:
|
||||
if considerQuotedIdent(x).s == "*":
|
||||
return newSymNode(ast.anyGlobal)
|
||||
result = c.semExpr(c, x)
|
||||
if result.kind != nkSym or sfGlobal notin result.sym.flags:
|
||||
localError(x.info, "'$1' is not a global variable" % result.renderTree)
|
||||
result = newSymNode(ast.anyGlobal)
|
||||
|
||||
if n.kind == nkExprColonExpr:
|
||||
let it = n.sons[1]
|
||||
if it.kind notin {nkCurly, nkBracket}:
|
||||
n.sons[1] = processExc(c, it)
|
||||
else:
|
||||
for i in 0 .. <it.len:
|
||||
it.sons[i] = processExc(c, it.sons[i])
|
||||
else:
|
||||
invalidPragma(n)
|
||||
|
||||
proc typeBorrow(sym: PSym, n: PNode) =
|
||||
if n.kind == nkExprColonExpr:
|
||||
let it = n.sons[1]
|
||||
@@ -542,11 +525,50 @@ proc typeBorrow(sym: PSym, n: PNode) =
|
||||
localError(n.info, "a type can only borrow `.` for now")
|
||||
incl(sym.typ.flags, tfBorrowDot)
|
||||
|
||||
proc markCompilerProc(s: PSym) =
|
||||
makeExternExport(s, "$1", s.info)
|
||||
incl(s.flags, sfCompilerProc)
|
||||
incl(s.flags, sfUsed)
|
||||
registerCompilerProc(s)
|
||||
|
||||
proc deprecatedStmt(c: PContext; pragma: PNode) =
|
||||
let pragma = pragma[1]
|
||||
if pragma.kind != nkBracket:
|
||||
localError(pragma.info, "list of key:value pairs expected"); return
|
||||
for n in pragma:
|
||||
if n.kind in {nkExprColonExpr, nkExprEqExpr}:
|
||||
let dest = qualifiedLookUp(c, n[1])
|
||||
let src = considerQuotedIdent(n[0])
|
||||
let alias = newSym(skAlias, src, dest, n[0].info)
|
||||
incl(alias.flags, sfExported)
|
||||
if sfCompilerProc in dest.flags: markCompilerProc(alias)
|
||||
addInterfaceDecl(c, alias)
|
||||
else:
|
||||
localError(n.info, "key:value pair expected")
|
||||
|
||||
proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
|
||||
if it.kind != nkExprColonExpr:
|
||||
invalidPragma(it); return
|
||||
let n = it[1]
|
||||
if n.kind == nkSym:
|
||||
result = n.sym
|
||||
elif kind == skField:
|
||||
# First check if the guard is a global variable:
|
||||
result = qualifiedLookUp(c, n, {})
|
||||
if result.isNil or result.kind notin {skLet, skVar} or
|
||||
sfGlobal notin result.flags:
|
||||
# We return a dummy symbol; later passes over the type will repair it.
|
||||
# Generic instantiation needs to know about this too. But we're lazy
|
||||
# and perform the lookup on demand instead.
|
||||
result = newSym(skUnknown, considerQuotedIdent(n), nil, n.info)
|
||||
else:
|
||||
result = qualifiedLookUp(c, n)
|
||||
|
||||
proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
validPragmas: TSpecialWords): bool =
|
||||
var it = n.sons[i]
|
||||
var key = if it.kind == nkExprColonExpr: it.sons[0] else: it
|
||||
if key.kind == nkIdent:
|
||||
if key.kind == nkIdent:
|
||||
var userPragma = strTableGet(c.userPragmas, key.ident)
|
||||
if userPragma != nil:
|
||||
inc c.instCounter
|
||||
@@ -578,11 +600,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
of wAlign:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
var align = expectIntLit(c, it)
|
||||
if not isPowerOfTwo(align) and align != 0:
|
||||
if (not isPowerOfTwo(align) and align != 0) or align >% high(int16):
|
||||
localError(it.info, errPowerOfTwoExpected)
|
||||
else:
|
||||
sym.typ.align = align
|
||||
of wSize:
|
||||
sym.typ.align = align.int16
|
||||
of wSize:
|
||||
if sym.typ == nil: invalidPragma(it)
|
||||
var size = expectIntLit(c, it)
|
||||
if not isPowerOfTwo(size) or size <= 0 or size > 8:
|
||||
@@ -648,17 +670,13 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
processDynLib(c, it, sym)
|
||||
of wCompilerproc:
|
||||
noVal(it) # compilerproc may not get a string!
|
||||
if sfFromGeneric notin sym.flags:
|
||||
makeExternExport(sym, "$1", it.info)
|
||||
incl(sym.flags, sfCompilerProc)
|
||||
incl(sym.flags, sfUsed) # suppress all those stupid warnings
|
||||
registerCompilerProc(sym)
|
||||
of wProcVar:
|
||||
if sfFromGeneric notin sym.flags: markCompilerProc(sym)
|
||||
of wProcVar:
|
||||
noVal(it)
|
||||
incl(sym.flags, sfProcvar)
|
||||
of wDeprecated:
|
||||
noVal(it)
|
||||
if sym != nil: incl(sym.flags, sfDeprecated)
|
||||
of wDeprecated:
|
||||
if it.kind == nkExprColonExpr: deprecatedStmt(c, it)
|
||||
elif sym != nil: incl(sym.flags, sfDeprecated)
|
||||
else: incl(c.module.flags, sfDeprecated)
|
||||
of wVarargs:
|
||||
noVal(it)
|
||||
@@ -789,10 +807,11 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
|
||||
if sym == nil: invalidPragma(it)
|
||||
of wLine: pragmaLine(c, it)
|
||||
of wRaises, wTags: pragmaRaisesOrTags(c, it)
|
||||
of wUses: pragmaUses(c, it)
|
||||
of wOperator:
|
||||
if sym == nil: invalidPragma(it)
|
||||
else: sym.position = expectIntLit(c, it)
|
||||
of wGuard:
|
||||
if sym == nil or sym.kind notin {skVar, skLet, skField}:
|
||||
invalidPragma(it)
|
||||
else:
|
||||
sym.guard = pragmaGuard(c, it, sym.kind)
|
||||
of wInjectStmt:
|
||||
if it.kind != nkExprColonExpr:
|
||||
localError(it.info, errExprExpected)
|
||||
|
||||
@@ -70,8 +70,15 @@ proc searchForProcNew(c: PContext, scope: PScope, fn: PSym): PSym =
|
||||
var it: TIdentIter
|
||||
result = initIdentIter(it, scope.symbols, fn.name)
|
||||
while result != nil:
|
||||
if result.kind in skProcKinds and
|
||||
sameType(result.typ, fn.typ, flags): return
|
||||
if result.kind in skProcKinds and sameType(result.typ, fn.typ, flags):
|
||||
case equalParams(result.typ.n, fn.typ.n)
|
||||
of paramsEqual:
|
||||
return
|
||||
of paramsIncompatible:
|
||||
localError(fn.info, errNotOverloadable, fn.name.s)
|
||||
return
|
||||
of paramsNotEqual:
|
||||
discard
|
||||
|
||||
result = nextIdentIter(it, scope.symbols)
|
||||
|
||||
|
||||
@@ -1614,6 +1614,11 @@ proc instantiateCreateFlowVarCall(c: PContext; t: PType;
|
||||
initIdTable(bindings)
|
||||
bindings.idTablePut(sym.ast[genericParamsPos].sons[0].typ, t)
|
||||
result = c.semGenerateInstance(c, sym, bindings, info)
|
||||
# since it's an instantiation, we unmark it as a compilerproc. Otherwise
|
||||
# codegen would fail:
|
||||
if sfCompilerProc in result.flags:
|
||||
result.flags = result.flags - {sfCompilerProc, sfExportC, sfImportC}
|
||||
result.loc.r = nil
|
||||
|
||||
proc setMs(n: PNode, s: PSym): PNode =
|
||||
result = n
|
||||
|
||||
@@ -315,7 +315,6 @@ proc documentRaises*(n: PNode) =
|
||||
if n.sons[namePos].kind != nkSym: return
|
||||
documentEffect(n, n.sons[pragmasPos], wRaises, exceptionEffects)
|
||||
documentEffect(n, n.sons[pragmasPos], wTags, tagEffects)
|
||||
documentEffect(n, n.sons[pragmasPos], wUses, usesEffects)
|
||||
|
||||
template notGcSafe(t): expr = {tfGcSafe, tfNoSideEffect} * t.flags == {}
|
||||
|
||||
@@ -335,10 +334,6 @@ proc propagateEffects(tracked: PEffects, n: PNode, s: PSym) =
|
||||
if warnGcUnsafe in gNotes: message(n.info, warnGcUnsafe, renderTree(n))
|
||||
tracked.gcUnsafe = true
|
||||
|
||||
when trackGlobals:
|
||||
let usesSpec = effectSpec(pragma, wUses)
|
||||
mergeUses(tracked, usesSpec, n)
|
||||
|
||||
proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) =
|
||||
let n = n.skipConv
|
||||
if paramType != nil and tfNotNil in paramType.flags and
|
||||
@@ -641,10 +636,6 @@ proc checkMethodEffects*(disp, branch: PSym) =
|
||||
if not isNil(tagsSpec):
|
||||
checkRaisesSpec(tagsSpec, actual.sons[tagEffects],
|
||||
"can have an unlisted effect: ", hints=off, subtypeRelation)
|
||||
let usesSpec = effectSpec(p, wUses)
|
||||
if not isNil(usesSpec):
|
||||
checkRaisesSpec(usesSpec, actual.sons[usesEffects],
|
||||
"may use an unlisted global variable: ", hints=off, symbolPredicate)
|
||||
if sfThread in disp.flags and notGcSafe(branch.typ):
|
||||
localError(branch.info, "base method is GC-safe, but '$1' is not" %
|
||||
branch.name.s)
|
||||
@@ -656,16 +647,13 @@ proc setEffectsForProcType*(t: PType, n: PNode) =
|
||||
let
|
||||
raisesSpec = effectSpec(n, wRaises)
|
||||
tagsSpec = effectSpec(n, wTags)
|
||||
usesSpec = effectSpec(n, wUses)
|
||||
if not isNil(raisesSpec) or not isNil(tagsSpec) or not isNil(usesSpec):
|
||||
if not isNil(raisesSpec) or not isNil(tagsSpec):
|
||||
internalAssert effects.len == 0
|
||||
newSeq(effects.sons, effectListLen)
|
||||
if not isNil(raisesSpec):
|
||||
effects.sons[exceptionEffects] = raisesSpec
|
||||
if not isNil(tagsSpec):
|
||||
effects.sons[tagEffects] = tagsSpec
|
||||
if not isNil(usesSpec):
|
||||
effects.sons[usesEffects] = usesSpec
|
||||
|
||||
proc initEffects(effects: PNode; s: PSym; t: var TEffects) =
|
||||
newSeq(effects.sons, effectListLen)
|
||||
@@ -710,12 +698,6 @@ proc trackProc*(s: PSym, body: PNode) =
|
||||
# after the check, use the formal spec:
|
||||
effects.sons[tagEffects] = tagsSpec
|
||||
|
||||
when trackGlobals:
|
||||
let usesSpec = effectSpec(p, wUses)
|
||||
if not isNil(usesSpec):
|
||||
checkRaisesSpec(usesSpec, t.uses,
|
||||
"uses an unlisted global variable: ", hints=on, symbolPredicate)
|
||||
effects.sons[usesEffects] = usesSpec
|
||||
if optThreadAnalysis in gGlobalOptions:
|
||||
if sfThread in s.flags and t.gcUnsafe:
|
||||
#localError(s.info, warnGcUnsafe2, s.name.s)
|
||||
|
||||
@@ -64,7 +64,7 @@ type
|
||||
wAcyclic, wShallow, wUnroll, wLinearScanEnd, wComputedGoto, wInjectStmt,
|
||||
wWrite, wGensym, wInject, wDirty, wInheritable, wThreadVar, wEmit,
|
||||
wAsmNoStackFrame,
|
||||
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wUses,
|
||||
wImplicitStatic, wGlobal, wCodegenDecl, wUnchecked, wGuard, wLocks,
|
||||
|
||||
wAuto, wBool, wCatch, wChar, wClass,
|
||||
wConst_cast, wDefault, wDelete, wDouble, wDynamic_cast,
|
||||
@@ -147,7 +147,7 @@ const
|
||||
"computedgoto", "injectstmt",
|
||||
"write", "gensym", "inject", "dirty", "inheritable", "threadvar", "emit",
|
||||
"asmnostackframe", "implicitstatic", "global", "codegendecl", "unchecked",
|
||||
"guard", "uses",
|
||||
"guard", "locks",
|
||||
|
||||
"auto", "bool", "catch", "char", "class",
|
||||
"const_cast", "default", "delete", "double",
|
||||
|
||||
@@ -41,7 +41,6 @@ doc.item = """
|
||||
<dt id="$itemSym"><a name="$itemSymOrID"></a><pre>$header</pre></dt>
|
||||
<dd>
|
||||
$desc
|
||||
$seeSrc
|
||||
</dd>
|
||||
"""
|
||||
|
||||
@@ -93,6 +92,11 @@ doc.file = """<?xml version="1.0" encoding="utf-8" ?>
|
||||
<title>$title</title>
|
||||
<style type="text/css">
|
||||
|
||||
body {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
span.DecNumber {color: blue}
|
||||
span.BinNumber {color: blue}
|
||||
span.HexNumber {color: blue}
|
||||
|
||||
@@ -130,10 +130,5 @@ vcc.options.always = "/nologo"
|
||||
vcc.options.speed = "/Ox /arch:SSE2"
|
||||
vcc.options.size = "/O1"
|
||||
|
||||
# Configuration for the Digital Mars C/C++ compiler:
|
||||
@if windows:
|
||||
dmc.path = r"$nimrod\dist\dm\bin"
|
||||
@end
|
||||
|
||||
# Configuration for the Tiny C Compiler:
|
||||
tcc.options.always = "-w"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
===============================================================================
|
||||
Nimrod -- a Compiler for Nimrod. http://nimrod-code.org/
|
||||
|
||||
Copyright (C) 2004-2014 Andreas Rumpf. All rights reserved.
|
||||
=====================================================
|
||||
Nimrod -- a Compiler for Nimrod. http://nimrod-lang.org/
|
||||
|
||||
Copyright (C) 2006-2014 Andreas Rumpf. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -35,3 +35,5 @@ Options:
|
||||
-r, --run run the compiled program with given arguments
|
||||
--advanced show advanced command line switches
|
||||
-h, --help show this help
|
||||
|
||||
Note: Even single letter options require the colon: -p:PATH.
|
||||
|
||||
@@ -4384,6 +4384,8 @@ helper distinct or object type has to be used for one pointer type.
|
||||
operator `=`
|
||||
------------
|
||||
|
||||
**Note**: Overriding the assignment operator has not yet been implemented.
|
||||
|
||||
This operator is the assignment operator. Note that in the contexts
|
||||
like ``let v = expr``, ``var v = expr``, ``parameter = defaultValue`` or for
|
||||
parameter passing no assignment is performed. The ``override`` pragma is
|
||||
@@ -5039,6 +5041,27 @@ first implementation to play with a language feature before a nicer syntax
|
||||
to access the feature becomes available.
|
||||
|
||||
|
||||
deprecated pragma
|
||||
-----------------
|
||||
|
||||
The deprecated pragma is used to mark a symbol as deprecated:
|
||||
|
||||
.. code-block:: nimrod
|
||||
proc p() {.deprecated.}
|
||||
var x {.deprecated.}: char
|
||||
|
||||
It can also be used as a statement. Then it takes a list of *renamings*. The
|
||||
upcoming ``nimfix`` tool can automatically update the code and perform these
|
||||
renamings:
|
||||
|
||||
.. code-block:: nimrod
|
||||
type
|
||||
File = object
|
||||
Stream = ref object
|
||||
{.deprecated: [TFile: File, PStream: Stream].}
|
||||
|
||||
|
||||
|
||||
noSideEffect pragma
|
||||
-------------------
|
||||
The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
|
||||
|
||||
@@ -16,6 +16,11 @@ customize this style sheet.
|
||||
Andreas Rumpf
|
||||
*/
|
||||
|
||||
body {
|
||||
color: black;
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
12
doc/tut2.txt
12
doc/tut2.txt
@@ -438,18 +438,6 @@ module. Example:
|
||||
echo "Got exception ", repr(e), " with message ", msg
|
||||
|
||||
|
||||
Exception hierarchy
|
||||
-------------------
|
||||
|
||||
If you want to create your own exceptions you can inherit from E_Base, but you
|
||||
can also inherit from one of the existing exceptions if they fit your purpose.
|
||||
The exception tree is:
|
||||
|
||||
.. include:: exception_hierarchy_fragment.txt
|
||||
|
||||
See the `system <system.html>`_ module for a description of each exception.
|
||||
|
||||
|
||||
Annotating procs with raised exceptions
|
||||
---------------------------------------
|
||||
|
||||
|
||||
@@ -58,8 +58,6 @@ Currently, the following C compilers are supported under Windows:
|
||||
| http://www.mingw.org/download.shtml
|
||||
- | LLVM with Clang or GNU C/C++ frontend
|
||||
| http://llvm.org/releases/download.html
|
||||
- | Digital Mars C++
|
||||
| http://www.digitalmars.com/download/freecompiler.html
|
||||
|
||||
However, most testing is done with GCC.
|
||||
|
||||
|
||||
37
koch.nim
37
koch.nim
@@ -43,7 +43,7 @@ Possible Commands:
|
||||
web generates the website
|
||||
csource [options] builds the C sources for installation
|
||||
zip builds the installation ZIP package
|
||||
inno [options] builds the Inno Setup installer (for Windows)
|
||||
nsis [options] builds the NSIS Setup installer (for Windows)
|
||||
tests [options] run the testsuite
|
||||
update updates nimrod to the latest version from github
|
||||
(compile koch with -d:withUpdate to enable)
|
||||
@@ -77,6 +77,14 @@ proc tryExec(cmd: string): bool =
|
||||
echo(cmd)
|
||||
result = execShellCmd(cmd) == 0
|
||||
|
||||
proc safeRemove(filename: string) =
|
||||
if existsFile(filename): removeFile(filename)
|
||||
|
||||
proc copyExe(source, dest: string) =
|
||||
safeRemove(dest)
|
||||
copyFile(dest=dest, source=source)
|
||||
inclFilePermissions(dest, {fpUserExec})
|
||||
|
||||
const
|
||||
compileNimInst = "-d:useLibzipSrc tools/niminst/niminst"
|
||||
|
||||
@@ -84,23 +92,28 @@ proc csource(args: string) =
|
||||
exec("$4 cc $1 -r $3 --var:version=$2 csource compiler/nimrod.ini $1" %
|
||||
[args, NimrodVersion, compileNimInst, findNim()])
|
||||
|
||||
proc zip(args: string) =
|
||||
exec("$3 cc -r $2 --var:version=$1 zip compiler/nimrod.ini" %
|
||||
proc zip(args: string) =
|
||||
exec("$3 cc -r $2 --var:version=$1 --var:mingw=mingw32 scripts compiler/nimrod.ini" %
|
||||
[NimrodVersion, compileNimInst, findNim()])
|
||||
exec("$# --var:version=$# --var:mingw=mingw32 zip compiler/nimrod.ini" %
|
||||
["tools/niminst/niminst".exe, NimrodVersion])
|
||||
|
||||
proc buildTool(toolname, args: string) =
|
||||
exec("$# cc $# $#" % [findNim(), args, toolname])
|
||||
copyFile(dest="bin"/ splitFile(toolname).name.exe, source=toolname.exe)
|
||||
|
||||
proc inno(args: string) =
|
||||
proc nsis(args: string) =
|
||||
# make sure we have generated the niminst executables:
|
||||
buildTool("tools/niminst/niminst", args)
|
||||
buildTool("tools/nimgrep", args)
|
||||
exec("tools" / "niminst" / "niminst --var:version=$# inno compiler/nimrod" %
|
||||
NimrodVersion)
|
||||
# produce 'nimrod_debug.exe':
|
||||
exec "nimrod c compiler" / "nimrod.nim"
|
||||
copyExe("compiler/nimrod".exe, "bin/nimrod_debug".exe)
|
||||
exec(("tools" / "niminst" / "niminst --var:version=$# --var:mingw=mingw32" &
|
||||
" nsis compiler/nimrod") % NimrodVersion)
|
||||
|
||||
proc install(args: string) =
|
||||
exec("$# cc -r $# --var:version=$# scripts compiler/nimrod.ini" %
|
||||
exec("$# cc -r $# --var:version=$# --var:mingw=mingw32 scripts compiler/nimrod.ini" %
|
||||
[findNim(), compileNimInst, NimrodVersion])
|
||||
exec("sh ./install.sh $#" % args)
|
||||
|
||||
@@ -135,16 +148,8 @@ proc findStartNimrod: string =
|
||||
echo("Found no nimrod compiler and every attempt to build one failed!")
|
||||
quit("FAILURE")
|
||||
|
||||
proc safeRemove(filename: string) =
|
||||
if existsFile(filename): removeFile(filename)
|
||||
|
||||
proc thVersion(i: int): string =
|
||||
result = ("compiler" / "nimrod" & $i).exe
|
||||
|
||||
proc copyExe(source, dest: string) =
|
||||
safeRemove(dest)
|
||||
copyFile(dest=dest, source=source)
|
||||
inclFilePermissions(dest, {fpUserExec})
|
||||
|
||||
proc boot(args: string) =
|
||||
var output = "compiler" / "nimrod".exe
|
||||
@@ -302,7 +307,7 @@ of cmdArgument:
|
||||
of "web": web(op.cmdLineRest)
|
||||
of "csource", "csources": csource(op.cmdLineRest)
|
||||
of "zip": zip(op.cmdLineRest)
|
||||
of "inno": inno(op.cmdLineRest)
|
||||
of "nsis": nsis(op.cmdLineRest)
|
||||
of "install": install(op.cmdLineRest)
|
||||
of "test", "tests": tests(op.cmdLineRest)
|
||||
of "update":
|
||||
|
||||
@@ -56,6 +56,8 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
|
||||
## Adds the file `src` to the archive `z` with the name `dest`. `dest`
|
||||
## may contain a path that will be created.
|
||||
assert(z.mode != fmRead)
|
||||
if not fileExists(src):
|
||||
raise newException(EIO, "File '" & src & "' does not exist")
|
||||
var zipsrc = zip_source_file(z.w, src, 0, -1)
|
||||
if zipsrc == nil:
|
||||
#echo("Dest: " & dest)
|
||||
|
||||
@@ -18,15 +18,24 @@ when not defined(windows):
|
||||
|
||||
when defined(linux):
|
||||
import linux
|
||||
|
||||
when defined(freebsd) or defined(macosx):
|
||||
{.emit:"#include <sys/types.h>".}
|
||||
|
||||
when defined(openbsd) or defined(netbsd):
|
||||
{.emit:"#include <sys/param.h>".}
|
||||
|
||||
when defined(macosx) or defined(bsd):
|
||||
# we HAVE to emit param.h before sysctl.h so we cannot use .header here
|
||||
# either. The amount of archaic bullshit in Poonix based OSes is just insane.
|
||||
{.emit:"#include <sys/sysctl.h>".}
|
||||
const
|
||||
CTL_HW = 6
|
||||
HW_AVAILCPU = 25
|
||||
HW_NCPU = 3
|
||||
proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
|
||||
a: var csize, b: pointer, c: int): cint {.
|
||||
importc: "sysctl", header: "<sys/sysctl.h>".}
|
||||
importc: "sysctl", nodecl.}
|
||||
|
||||
proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
|
||||
## returns the numer of the processors/cores the machine has.
|
||||
|
||||
@@ -95,7 +95,7 @@ type
|
||||
|
||||
FlowVarBase* = ref FlowVarBaseObj ## untyped base class for 'FlowVar[T]'
|
||||
FlowVarBaseObj = object of TObject
|
||||
ready, usesCondVar: bool
|
||||
ready, usesCondVar, awaited: bool
|
||||
cv: CondVar #\
|
||||
# for 'awaitAny' support
|
||||
ai: ptr AwaitInfo
|
||||
@@ -129,8 +129,8 @@ type
|
||||
proc await*(fv: FlowVarBase) =
|
||||
## waits until the value for the flowVar arrives. Usually it is not necessary
|
||||
## to call this explicitly.
|
||||
if fv.usesCondVar:
|
||||
fv.usesCondVar = false
|
||||
if fv.usesCondVar and not fv.awaited:
|
||||
fv.awaited = true
|
||||
await(fv.cv)
|
||||
destroyCondVar(fv.cv)
|
||||
|
||||
|
||||
@@ -78,10 +78,23 @@ when defined(macosx):
|
||||
else:
|
||||
template SIGBUS: expr = SIGSEGV
|
||||
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "setjmp".}
|
||||
when defined(nimSigSetjmp) and not defined(nimStdSetjmp):
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "siglongjmp".}
|
||||
template c_setjmp(jmpb: C_JmpBuf): cint =
|
||||
proc c_sigsetjmp(jmpb: C_JmpBuf, savemask: cint): cint {.
|
||||
header: "<setjmp.h>", importc: "sigsetjmp".}
|
||||
c_sigsetjmp(jmpb, 0)
|
||||
elif defined(nimRawSetjmp) and not defined(nimStdSetjmp):
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "_longjmp".}
|
||||
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "_setjmp".}
|
||||
else:
|
||||
proc c_longjmp(jmpb: C_JmpBuf, retval: cint) {.
|
||||
header: "<setjmp.h>", importc: "longjmp".}
|
||||
proc c_setjmp(jmpb: C_JmpBuf): cint {.
|
||||
header: "<setjmp.h>", importc: "setjmp".}
|
||||
|
||||
proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {.
|
||||
importc: "signal", header: "<signal.h>".}
|
||||
|
||||
@@ -226,15 +226,16 @@ proc recv*[TMsg](c: var TChannel[TMsg]): TMsg =
|
||||
llRecv(q, addr(result), cast[PNimType](getTypeInfo(result)))
|
||||
releaseSys(q.lock)
|
||||
|
||||
proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvaliable: bool,
|
||||
proc tryRecv*[TMsg](c: var TChannel[TMsg]): tuple[dataAvailable: bool,
|
||||
msg: TMsg] =
|
||||
## try to receives a message from the channel `c` if available. Otherwise
|
||||
## it returns ``(false, default(msg))``.
|
||||
var q = cast[PRawChannel](addr(c))
|
||||
if q.mask != ChannelDeadMask:
|
||||
lockChannel(q):
|
||||
if q.mask != ChannelDeadMask:
|
||||
if tryAcquireSys(q.lock):
|
||||
llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg)))
|
||||
result.dataAvaliable = true
|
||||
result.dataAvailable = true
|
||||
releaseSys(q.lock)
|
||||
|
||||
proc peek*[TMsg](c: var TChannel[TMsg]): int =
|
||||
## returns the current number of messages in the channel `c`. Returns -1
|
||||
|
||||
@@ -62,5 +62,5 @@ allowing you to create commercial applications.
|
||||
|
||||
Read copying.txt for more details.
|
||||
|
||||
Copyright (c) 2004-2014 Andreas Rumpf.
|
||||
Copyright (c) 2006-2014 Andreas Rumpf.
|
||||
All rights reserved.
|
||||
|
||||
60
readme.txt
60
readme.txt
@@ -1,60 +1,12 @@
|
||||
# Nimrod Compiler
|
||||
This repo contains the Nimrod compiler, Nimrod's stdlib, tools and
|
||||
This package contains the Nimrod compiler, Nimrod's stdlib, tools and
|
||||
documentation.
|
||||
|
||||
## Compiling
|
||||
Compiling the Nimrod compiler is quite straightforward. Because
|
||||
the Nimrod compiler itself is written in the Nimrod programming language
|
||||
the C source of an older version of the compiler are needed to bootstrap the
|
||||
latest version. The C sources are available in a separate repo [here](http://github.com/nimrod-code/csources).
|
||||
Nimrod is a compiled, garbage-collected systems programming language which has
|
||||
an excellent productivity/performance ratio. Nimrod's design focuses on
|
||||
efficiency, expressiveness, elegance (in the order of priority).
|
||||
|
||||
Pre-compiled snapshots of the compiler are also available on
|
||||
[Nimbuild](http://build.nimrod-lang.org/). Your platform however may not
|
||||
currently be built for.
|
||||
Read install.txt for instructions of how to build and install it.
|
||||
|
||||
The compiler currently supports the following platform and architecture
|
||||
combinations:
|
||||
|
||||
* Windows (Windows XP or greater) - x86 and x86_64
|
||||
* Linux (most, if not all, distributions) - x86, x86_64, ppc64 and armv6l
|
||||
* Mac OS X 10.04 or higher - x86, x86_64 and ppc64
|
||||
|
||||
In reality a lot more are supported, however they are not tested regularly.
|
||||
|
||||
To build from source you will need:
|
||||
|
||||
* gcc 3.x or later recommended. Other alternatives which may work
|
||||
are: clang, Visual C++, Intel's C++ compiler
|
||||
* git or wget
|
||||
|
||||
If you are on a fairly modern *nix system, the following steps should work:
|
||||
|
||||
```
|
||||
$ git clone git://github.com/Araq/Nimrod.git
|
||||
$ cd Nimrod
|
||||
$ git clone --depth 1 git://github.com/nimrod-code/csources
|
||||
$ cd csources && ./build.sh
|
||||
$ cd ..
|
||||
$ bin/nimrod c koch
|
||||
$ ./koch boot -d:release
|
||||
```
|
||||
|
||||
``koch install [dir]`` may then be used to install Nimrod, or you can simply
|
||||
add it to your PATH. More ``koch`` related options are documented in
|
||||
[doc/koch.txt](doc/koch.txt).
|
||||
|
||||
The above steps can be performed on Windows in a similar fashion, the
|
||||
``build.bat`` and ``build64.bat`` (for x86_64 systems) are provided to be used
|
||||
instead of ``build.sh``.
|
||||
|
||||
## Getting help
|
||||
A [forum](http://forum.nimrod-lang.org/) is available if you have any
|
||||
questions, and you can also get help in the IRC channel on
|
||||
[Freenode](irc://irc.freenode.net/nimrod) in #nimrod. If you ask questions on
|
||||
[StackOverflow use the nimrod
|
||||
tag](http://stackoverflow.com/questions/tagged/nimrod).
|
||||
|
||||
## License
|
||||
The compiler and the standard library are licensed under the MIT license,
|
||||
except for some modules where the documentation suggests otherwise. This means
|
||||
that you can use any license for your own programs developed with Nimrod,
|
||||
@@ -62,5 +14,5 @@ allowing you to create commercial applications.
|
||||
|
||||
Read copying.txt for more details.
|
||||
|
||||
Copyright (c) 2004-2014 Andreas Rumpf.
|
||||
Copyright (c) 2006-2014 Andreas Rumpf.
|
||||
All rights reserved.
|
||||
|
||||
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]
|
||||
function GiveMeAPath(const DefaultPathName: string): string;
|
||||
begin
|
||||
if IsAdminLoggedOn then Result := ExpandConstant('{pf}')
|
||||
else Result := ExpandConstant('{userdocs}');
|
||||
Result := Result + '\' + DefaultPathName;
|
||||
if IsAdminLoggedOn then result := ExpandConstant('{pf}')
|
||||
else result := ExpandConstant('{userdocs}');
|
||||
result := result + '\' + DefaultPathName;
|
||||
end;
|
||||
|
||||
#if c.binPaths.len > 0:
|
||||
|
||||
@@ -31,6 +31,7 @@ type
|
||||
actionNone, # action not yet known
|
||||
actionCSource # action: create C sources
|
||||
actionInno, # action: create Inno Setup installer
|
||||
actionNsis, # action: create NSIS installer
|
||||
actionScripts # action: create install and deinstall scripts
|
||||
actionZip, # action: create zip file
|
||||
actionDeb # action: prepare deb package
|
||||
@@ -50,10 +51,10 @@ type
|
||||
TConfigData = object of TObject
|
||||
actions: set[TAction]
|
||||
cat: array[TFileCategory, seq[string]]
|
||||
binPaths, authors, oses, cpus: seq[string]
|
||||
binPaths, authors, oses, cpus, downloads: seq[string]
|
||||
cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
|
||||
platforms: array[1..maxOS, array[1..maxCPU, bool]]
|
||||
ccompiler, linker, innosetup: tuple[path, flags: string]
|
||||
ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
|
||||
name, displayName, version, description, license, infile, outdir: string
|
||||
libpath: string
|
||||
innoSetupFlag, installScript, uninstallScript: bool
|
||||
@@ -75,9 +76,11 @@ proc initConfigData(c: var TConfigData) =
|
||||
c.authors = @[]
|
||||
c.oses = @[]
|
||||
c.cpus = @[]
|
||||
c.downloads = @[]
|
||||
c.ccompiler = ("", "")
|
||||
c.linker = ("", "")
|
||||
c.innosetup = ("", "")
|
||||
c.nsisSetup = ("", "")
|
||||
c.name = ""
|
||||
c.displayName = ""
|
||||
c.version = ""
|
||||
@@ -117,6 +120,7 @@ proc skipRoot(f: string): string =
|
||||
if result.len == 0: result = f
|
||||
|
||||
include "inno.tmpl"
|
||||
include "nsis.tmpl"
|
||||
include "buildsh.tmpl"
|
||||
include "buildbat.tmpl"
|
||||
include "install.tmpl"
|
||||
@@ -125,10 +129,10 @@ include "deinstall.tmpl"
|
||||
# ------------------------- configuration file -------------------------------
|
||||
|
||||
const
|
||||
Version = "0.9"
|
||||
Version = "1.0"
|
||||
Usage = "niminst - Nimrod Installation Generator Version " & Version & """
|
||||
|
||||
(c) 2013 Andreas Rumpf
|
||||
(c) 2014 Andreas Rumpf
|
||||
Usage:
|
||||
niminst [options] command[;command2...] ini-file[.ini] [compile_options]
|
||||
Command:
|
||||
@@ -136,6 +140,7 @@ Command:
|
||||
scripts build install and deinstall scripts
|
||||
zip build the ZIP file
|
||||
inno build the Inno Setup installer
|
||||
nsis build the NSIS Setup installer
|
||||
deb create files for debhelper
|
||||
Options:
|
||||
-o, --output:dir set the output directory
|
||||
@@ -162,6 +167,7 @@ proc parseCmdLine(c: var TConfigData) =
|
||||
of "scripts": incl(c.actions, actionScripts)
|
||||
of "zip": incl(c.actions, actionZip)
|
||||
of "inno": incl(c.actions, actionInno)
|
||||
of "nsis": incl(c.actions, actionNsis)
|
||||
of "deb": incl(c.actions, actionDeb)
|
||||
else: quit(Usage)
|
||||
else:
|
||||
@@ -190,7 +196,7 @@ proc walkDirRecursively(s: var seq[string], root: string) =
|
||||
case k
|
||||
of pcFile, pcLinkToFile: add(s, unixToNativePath(f))
|
||||
of pcDir: walkDirRecursively(s, f)
|
||||
of pcLinkToDir: nil
|
||||
of pcLinkToDir: discard
|
||||
|
||||
proc addFiles(s: var seq[string], patterns: seq[string]) =
|
||||
for p in items(patterns):
|
||||
@@ -288,7 +294,7 @@ proc parseIniFile(c: var TConfigData) =
|
||||
else: quit(errorStr(p, "expected: console or gui"))
|
||||
of "license": c.license = unixToNativePath(k.value)
|
||||
else: quit(errorStr(p, "unknown variable: " & k.key))
|
||||
of "var": nil
|
||||
of "var": discard
|
||||
of "winbin": filesOnly(p, k.key, v, c.cat[fcWinBin])
|
||||
of "config": filesOnly(p, k.key, v, c.cat[fcConfig])
|
||||
of "data": filesOnly(p, k.key, v, c.cat[fcData])
|
||||
@@ -304,6 +310,7 @@ proc parseIniFile(c: var TConfigData) =
|
||||
of "files": addFiles(c.cat[fcWindows], split(v, {';'}))
|
||||
of "binpath": c.binPaths = split(v, {';'})
|
||||
of "innosetup": c.innoSetupFlag = yesno(p, v)
|
||||
of "download": c.downloads.add(v)
|
||||
else: quit(errorStr(p, "unknown variable: " & k.key))
|
||||
of "unix":
|
||||
case normalize(k.key)
|
||||
@@ -313,6 +320,7 @@ proc parseIniFile(c: var TConfigData) =
|
||||
else: quit(errorStr(p, "unknown variable: " & k.key))
|
||||
of "unixbin": filesOnly(p, k.key, v, c.cat[fcUnixBin])
|
||||
of "innosetup": pathFlags(p, k.key, v, c.innosetup)
|
||||
of "nsis": pathFlags(p, k.key, v, c.nsisSetup)
|
||||
of "ccompiler": pathFlags(p, k.key, v, c.ccompiler)
|
||||
of "linker": pathFlags(p, k.key, v, c.linker)
|
||||
of "deb":
|
||||
@@ -479,14 +487,14 @@ proc srcdist(c: var TConfigData) =
|
||||
|
||||
# --------------------- generate inno setup -----------------------------------
|
||||
proc setupDist(c: var TConfigData) =
|
||||
var scrpt = generateInnoSetup(c)
|
||||
var n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
|
||||
let scrpt = generateInnoSetup(c)
|
||||
let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
|
||||
writeFile(n, scrpt, "\13\10")
|
||||
when defined(windows):
|
||||
if c.innosetup.path.len == 0:
|
||||
c.innosetup.path = "iscc.exe"
|
||||
var outcmd = if c.outdir.len == 0: "build" else: c.outdir
|
||||
var cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
|
||||
let outcmd = if c.outdir.len == 0: "build" else: c.outdir
|
||||
let cmd = "$# $# /O$# $#" % [quoteShell(c.innosetup.path),
|
||||
c.innosetup.flags, outcmd, n]
|
||||
echo(cmd)
|
||||
if execShellCmd(cmd) == 0:
|
||||
@@ -494,6 +502,23 @@ proc setupDist(c: var TConfigData) =
|
||||
else:
|
||||
quit("External program failed")
|
||||
|
||||
# --------------------- generate NSIS setup -----------------------------------
|
||||
proc setupDist2(c: var TConfigData) =
|
||||
let scrpt = generateNsisSetup(c)
|
||||
let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
|
||||
writeFile(n, scrpt, "\13\10")
|
||||
when defined(windows):
|
||||
if c.nsisSetup.path.len == 0:
|
||||
c.nsisSetup.path = "makensis.exe"
|
||||
let outcmd = if c.outdir.len == 0: "build" else: c.outdir
|
||||
let cmd = "$# $# /O$# $#" % [quoteShell(c.nsisSetup.path),
|
||||
c.nsisSetup.flags, outcmd, n]
|
||||
echo(cmd)
|
||||
if execShellCmd(cmd) == 0:
|
||||
removeFile(n)
|
||||
else:
|
||||
quit("External program failed")
|
||||
|
||||
# ------------------ generate ZIP file ---------------------------------------
|
||||
when haveZipLib:
|
||||
proc zipDist(c: var TConfigData) =
|
||||
@@ -503,17 +528,17 @@ when haveZipLib:
|
||||
else: n = c.outdir / n
|
||||
var z: TZipArchive
|
||||
if open(z, n, fmWrite):
|
||||
addFile(z, proj / buildBatFile32, buildBatFile32)
|
||||
addFile(z, proj / buildBatFile64, buildBatFile64)
|
||||
addFile(z, proj / buildShFile, buildShFile)
|
||||
addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
|
||||
addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
|
||||
addFile(z, proj / buildShFile, "build" / buildShFile)
|
||||
addFile(z, proj / installShFile, installShFile)
|
||||
addFile(z, proj / deinstallShFile, deinstallShFile)
|
||||
for f in walkFiles(c.libpath / "lib/*.h"):
|
||||
addFile(z, proj / "build" / extractFilename(f), f)
|
||||
addFile(z, proj / "c_code" / extractFilename(f), f)
|
||||
for osA in 1..c.oses.len:
|
||||
for cpuA in 1..c.cpus.len:
|
||||
var dir = buildDir(osA, cpuA)
|
||||
for k, f in walkDir(dir):
|
||||
for k, f in walkDir("build" / dir):
|
||||
if k == pcFile: addFile(z, proj / dir / extractFilename(f), f)
|
||||
|
||||
for cat in items({fcConfig..fcOther, fcUnix}):
|
||||
@@ -576,6 +601,8 @@ parseCmdLine(c)
|
||||
parseIniFile(c)
|
||||
if actionInno in c.actions:
|
||||
setupDist(c)
|
||||
if actionNsis in c.actions:
|
||||
setupDist2(c)
|
||||
if actionCSource in c.actions:
|
||||
srcdist(c)
|
||||
if actionScripts in c.actions:
|
||||
|
||||
255
tools/niminst/nsis.tmpl
Normal file
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.numProcessors = countProcessors()
|
||||
# Attempts to obtain the git current commit.
|
||||
let (output, code) = execCmdEx("git log -n 1 --format=%H")
|
||||
if code == 0 and output.strip.len == 40:
|
||||
c.gitCommit = output.strip
|
||||
when false:
|
||||
let (output, code) = execCmdEx("git log -n 1 --format=%H")
|
||||
if code == 0 and output.strip.len == 40:
|
||||
c.gitCommit = output.strip
|
||||
c.quotations = initTable[string, tuple[quote, author: string]]()
|
||||
|
||||
include "website.tmpl"
|
||||
@@ -239,7 +240,7 @@ proc mexec(cmds: openarray[string], processors: int) =
|
||||
sexec(cmds)
|
||||
return
|
||||
|
||||
if 0 != execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}):
|
||||
if execProcesses(cmds, {poStdErrToStdOut, poParentStreams, poEchoCmd}) != 0:
|
||||
echo "external program failed, retrying serial work queue for logs!"
|
||||
sexec(cmds)
|
||||
|
||||
@@ -289,8 +290,10 @@ proc buildPdfDoc(c: var TConfigData, destPath: string) =
|
||||
exec("pdflatex " & changeFileExt(d, "tex"))
|
||||
exec("pdflatex " & changeFileExt(d, "tex"))
|
||||
# delete all the crappy temporary files:
|
||||
var pdf = splitFile(d).name & ".pdf"
|
||||
moveFile(dest=destPath / pdf, source=pdf)
|
||||
let pdf = splitFile(d).name & ".pdf"
|
||||
let dest = destPath / pdf
|
||||
removeFile(dest)
|
||||
moveFile(dest=dest, source=pdf)
|
||||
removeFile(changeFileExt(pdf, "aux"))
|
||||
if existsFile(changeFileExt(pdf, "toc")):
|
||||
removeFile(changeFileExt(pdf, "toc"))
|
||||
@@ -432,4 +435,7 @@ var c: TConfigData
|
||||
initConfigData(c)
|
||||
parseCmdLine(c)
|
||||
parseIniFile(c)
|
||||
main(c)
|
||||
when false:
|
||||
buildPdfDoc(c, "doc")
|
||||
else:
|
||||
main(c)
|
||||
|
||||
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
|
||||
use the binaries provided or build from source.
|
||||
|
||||
Binaries
|
||||
========
|
||||
|
||||
All installers and archives contain the html documentation and tools
|
||||
(nimgrep, c2nim and babel).
|
||||
You can download the latest version of the Nimrod compiler here.
|
||||
|
||||
**Note:** The Nimrod compiler requires a C compiler to compile software. On
|
||||
Windows we recommend that you use
|
||||
`Mingw-w64 <http://mingw-w64.sourceforge.net/>`_. GCC is recommended on Linux
|
||||
and clang on Mac OS X.
|
||||
|
||||
Installers
|
||||
----------
|
||||
|
||||
The "full" version includes a full mingw distribution which includes a C
|
||||
compiler. The "slim" version lacks this.
|
||||
Binaries
|
||||
========
|
||||
|
||||
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.exe>`_
|
||||
Unfortunately for now we only provide builds for Windows.
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: dca7c63d0c1861d2d7c51b2e7a29fa98371750a10ab282d5df9de22a07719c24
|
||||
</p>
|
||||
* 32 bit: `nimrod_0.9.6.exe <download/nimrod_0.9.6.exe>`_
|
||||
* 64 bit: `nimrod_0.9.6_x64.exe <download/nimrod_0.9.6_x64.exe>`_
|
||||
|
||||
* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.exe>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: c0fcd1201bd20fad1e14b9d2cc2529494057068de1dd01f871cf129f088a8242
|
||||
</p>
|
||||
Installation based on generated C code
|
||||
======================================
|
||||
|
||||
* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.exe>`_
|
||||
This installation method is the preferred way for Linux, Mac OS X, and other Unix
|
||||
like systems. Binary packages may be provided later.
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: af9d478c2f3361e0f238fcb07fa8e7ae5821938c0f9063c6670e925c9ae9d16e
|
||||
</p>
|
||||
|
||||
* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.exe>`_
|
||||
Download `nimrod_0.9.6.zip <download/nimrod_0.9.6.zip>`_, extract it and follow
|
||||
these instructions:
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 90c380721a46be2b9b8d5437187f701940aefc2e1fb9722dbc543f5c5a3bb85e
|
||||
</p>
|
||||
* sh build.sh
|
||||
* Add ``$your_install_dir/bin`` to your PATH.
|
||||
|
||||
Archives
|
||||
--------
|
||||
There are other ways to install Nimrod (like using the ``install.sh`` script),
|
||||
but these tend to cause more problems.
|
||||
|
||||
Windows
|
||||
~~~~~~~
|
||||
|
||||
The "full" version includes a full mingw distribution which includes a C
|
||||
compiler. The "slim" version lacks this.
|
||||
Installation from github
|
||||
========================
|
||||
|
||||
* Full (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_full.zip>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 8ee18faaa3a3d5df482c7abd6aa7ea87a350d7328b80ce1e2d486b59a7a93956
|
||||
</p>
|
||||
|
||||
* Slim (i386, 32bit): `<download/nimrod_0.9.4_windows_i386_slim.zip>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 7024fb8ad8f98c0bd4949ae36ed11b52b4e401754bbd62a11199d6dc8628d857
|
||||
</p>
|
||||
|
||||
* Full (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_full.zip>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: cb33cacc1a84fec771323d24cb6d9795f4803882466a9f417b424990aa49e18a
|
||||
</p>
|
||||
|
||||
* Slim (amd64, 64bit): `<download/nimrod_0.9.4_windows_amd64_slim.zip>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: fcf877e4bd1ebfa214749af6e4811cd8539af19f1d7b23017e4bd7f6cbfb3eba
|
||||
</p>
|
||||
|
||||
Linux
|
||||
~~~~~
|
||||
|
||||
* Linux (i386, 32bit): `<download/nimrod_0.9.4_linux_i386.tar.gz>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 79DD337A77AC4313A75F2C5EED8252F00BBBDEB1E0C3504660D4A52EA63DBA92
|
||||
</p>
|
||||
* Linux (amd64, 64bit): `<download/nimrod_0.9.4_linux_amd64.tar.gz>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 6F6CB3C727BA8059B7605C02942AE7910C20C2A3DC6A8A600D90D50FE61F0D8C
|
||||
</p>
|
||||
* Linux (ppc64, 64bit): `<download/nimrod_0.9.4_linux_ppc64.tar.gz>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: 5DAC2D9F7F545929E04540E6E2594C68FC3126A3B2F7B1FA7DBA5E295B4A7D31
|
||||
</p>
|
||||
|
||||
Mac OS X
|
||||
~~~~~~~~
|
||||
|
||||
* Mac OS X (amd64, 64bit): `<download/nimrod_0.9.4_macosx_amd64.zip>`_
|
||||
|
||||
.. raw:: html
|
||||
<p style="font-size: 8pt; margin-top: 0;">
|
||||
SHA256: E6F3A8E434DF3E89686F043954C6DFC09ABEBC0FC09D3B9A6B35C2B3102F7C3C
|
||||
</p>
|
||||
|
||||
If a binary for your platform is not available then you must build from source.
|
||||
Bleeding edge binaries are available from the `Nimrod build farm <http://build.nimrod-lang.org/>`_.
|
||||
|
||||
Source
|
||||
======
|
||||
|
||||
Starting with 0.9.4 we now advise people to build directly from the
|
||||
It is also possible to build directly from the
|
||||
github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
|
||||
|
||||
git clone -b master git://github.com/Araq/Nimrod.git
|
||||
@@ -135,4 +49,3 @@ github `master <https://github.com/Araq/Nimrod#compiling>`_ branch::
|
||||
The ``master`` branch always contains the latest stable version of the compiler.
|
||||
If you want bleeding edge then switch to the ``devel`` branch and follow
|
||||
the same instructions outlined above.
|
||||
|
||||
|
||||
87
web/news.txt
87
web/news.txt
@@ -2,51 +2,60 @@
|
||||
News
|
||||
====
|
||||
|
||||
..
|
||||
2014-06-29 Version 0.9.6 released
|
||||
=================================
|
||||
2014-10-19 Nimrod version 0.9.6 released
|
||||
========================================
|
||||
|
||||
Changes affecting backwards compatibility
|
||||
-----------------------------------------
|
||||
**Note: 0.9.6 is the last release of Nimrod. The language has been renamed to
|
||||
Nim. Nim slightly breaks compatibility.**
|
||||
|
||||
- ``spawn`` now uses an elaborate self-adapting thread pool and as such
|
||||
has been moved into its own module. So to use it, you now have to import
|
||||
``threadpool``.
|
||||
- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
|
||||
now considered for implicit early binding.
|
||||
- ``c2nim`` moved into its own repository and is now a Babel package.
|
||||
- ``pas2nim`` moved into its own repository and is now a Babel package.
|
||||
- ``system.$`` for floating point types now produces a human friendly string
|
||||
representation.
|
||||
- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
|
||||
of the new ``TUri`` type in the ``uri`` module.
|
||||
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
|
||||
instead. The destructor's name has to be ``destroy`` now.
|
||||
- ``lambda`` is not a keyword anymore.
|
||||
- **system.defined has been split into system.defined and system.declared**.
|
||||
You have to use ``--symbol`` to declare new conditional symbols that can be
|
||||
set via ``--define``.
|
||||
- ``--threadanalysis:on`` is now the default. To make your program compile
|
||||
you can disable it but this is only a temporary solution as this option
|
||||
will disappear soon!
|
||||
|
||||
This is a maintenance release. The upcoming 0.10.0 release has
|
||||
the new features and exciting developments.
|
||||
|
||||
Language Additions
|
||||
------------------
|
||||
|
||||
- There is a new ``parallel`` statement for safe fork&join parallel computing.
|
||||
|
||||
Changes affecting backwards compatibility
|
||||
-----------------------------------------
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
- ``spawn`` now uses an elaborate self-adapting thread pool and as such
|
||||
has been moved into its own module. So to use it, you now have to import
|
||||
``threadpool``.
|
||||
- The symbol binding rules in generics changed: ``bar`` in ``foo.bar`` is
|
||||
now considered for implicit early binding.
|
||||
- ``c2nim`` moved into its own repository and is now a Babel package.
|
||||
- ``pas2nim`` moved into its own repository and is now a Babel package.
|
||||
- ``system.$`` for floating point types now produces a human friendly string
|
||||
representation.
|
||||
- ``uri.TUrl`` as well as the ``parseurl`` module are now deprecated in favour
|
||||
of the new ``TUri`` type in the ``uri`` module.
|
||||
- The ``destructor`` pragma has been deprecated. Use the ``override`` pragma
|
||||
instead. The destructor's name has to be ``destroy`` now.
|
||||
- ``lambda`` is not a keyword anymore.
|
||||
- **system.defined has been split into system.defined and system.declared**.
|
||||
You have to use ``--symbol`` to declare new conditional symbols that can be
|
||||
set via ``--define``.
|
||||
- ``--threadanalysis:on`` is now the default. To make your program compile
|
||||
you can disable it but this is only a temporary solution as this option
|
||||
will disappear soon!
|
||||
|
||||
- Added module ``cpuinfo``.
|
||||
- Added module ``threadpool``.
|
||||
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
|
||||
- Added ``algorithm.reversed``
|
||||
- Added ``uri.combine`` and ``uri.parseUri``.
|
||||
- Some sockets procedures now support a ``SafeDisconn`` flag which causes
|
||||
them to handle disconnection errors and not raise them.
|
||||
|
||||
Language Additions
|
||||
------------------
|
||||
|
||||
- This version introduces the new ``deprecated`` pragma statement that is used
|
||||
to handle the upcoming massive amount of symbol renames.
|
||||
- ``spawn`` can now wrap proc that have a return value. It then returns a flow
|
||||
variable of the wrapped return type.
|
||||
|
||||
|
||||
Library Additions
|
||||
-----------------
|
||||
|
||||
- Added module ``cpuinfo``.
|
||||
- Added module ``threadpool``.
|
||||
- ``sequtils.distnct`` has been renamed to ``sequtils.deduplicate``.
|
||||
- Added ``algorithm.reversed``
|
||||
- Added ``uri.combine`` and ``uri.parseUri``.
|
||||
- Some sockets procedures now support a ``SafeDisconn`` flag which causes
|
||||
them to handle disconnection errors and not raise them.
|
||||
|
||||
|
||||
2014-04-21 Version 0.9.4 released
|
||||
|
||||
@@ -26,9 +26,10 @@ file: ticker.txt
|
||||
[Quotations]
|
||||
# Page: quote - Person
|
||||
# Bad things will happen if you use multiple dashes here.
|
||||
index: """The most important thing in the programming language is the name.
|
||||
A language will not succeed without a good name. I have recently invented a
|
||||
very good name and now I am looking for a suitable language. - D. E. Knuth"""
|
||||
index: """Is it so bad, then, to be misunderstood? Pythagoras was misunderstood,
|
||||
and Socrates, and Jesus, and Luther, and Copernicus, and Galileo, and Newton,
|
||||
and every pure and wise spirit that ever took flesh. To be great is to be
|
||||
misunderstood. - Ralph Waldo Emerson"""
|
||||
documentation: """Incorrect documentation is often worse than no documentation.
|
||||
- Bertrand Meyer"""
|
||||
download: """There are two major products that come out of Berkeley: LSD and
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
<a class="news" href="news.html#Z2014-10-19-version-0-9-6-released">
|
||||
<h3>Oct 19, 2014</h3>
|
||||
<p>Nimrod version 0.9.6 has been released!</p>
|
||||
</a>
|
||||
|
||||
<a class="news" href="news.html#Z2014-04-21-version-0-9-4-released">
|
||||
<h3>Apr 21, 2014</h3>
|
||||
<p>Nimrod version 0.9.4 has been released!</p>
|
||||
|
||||
Reference in New Issue
Block a user