Merge branch 'devel' of github.com:nim-lang/Nim into devel

This commit is contained in:
Araq
2016-07-14 01:11:47 +02:00
34 changed files with 361 additions and 75 deletions

View File

@@ -965,7 +965,6 @@ const
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
var
gMainPackageId*: int
gMainPackageNotes*: TNoteKinds
proc isCallExpr*(n: PNode): bool =
result = n.kind in nkCallKinds

View File

@@ -150,6 +150,9 @@ proc mapType(typ: PType): TCTypeKind =
of tyCString: result = ctCString
of tyInt..tyUInt64:
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
of tyStatic:
if typ.n != nil: result = mapType(lastSon typ)
else: internalError("mapType")
else: internalError("mapType")
proc mapReturnType(typ: PType): TCTypeKind =
@@ -256,6 +259,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
of tyInt..tyUInt64:
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.kind])
of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.sons[0])
of tyStatic:
if typ.n != nil: result = getSimpleTypeDesc(m, lastSon typ)
else: internalError("tyStatic for getSimpleTypeDesc")
of tyGenericInst:
result = getSimpleTypeDesc(m, lastSon typ)
else: result = nil
proc pushType(m: BModule, typ: PType) =
@@ -1025,6 +1033,9 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
of tyEmpty, tyVoid: result = rope"0"
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
genTypeInfoAuxBase(m, t, t, result, rope"0")
of tyStatic:
if t.n != nil: result = genTypeInfo(m, lastSon t)
else: internalError("genTypeInfo(" & $t.kind & ')')
of tyProc:
if t.callConv != ccClosure:
genTypeInfoAuxBase(m, t, t, result, rope"0")

View File

@@ -181,9 +181,11 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
case whichKeyword(substr(arg, i))
of wOn:
incl(gNotes, n)
incl(gMainPackageNotes, n)
incl(enableNotes, n)
of wOff:
excl(gNotes, n)
excl(gMainPackageNotes, n)
incl(disableNotes, n)
excl(ForeignPackageNotes, n)
else: localError(info, errOnOrOffExpectedButXFound, arg)
@@ -548,6 +550,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
gNotes = NotesVerbosity[gVerbosity]
incl(gNotes, enableNotes)
excl(gNotes, disableNotes)
gMainPackageNotes = gNotes
of "parallelbuild":
expectArg(switch, arg, pass, info)
gNumberOfProcessors = parseInt(arg)

View File

@@ -14,7 +14,7 @@
import
ast, strutils, strtabs, options, msgs, os, ropes, idents,
wordrecg, syntaxes, renderer, lexer, rstast, rst, rstgen, times, highlite,
importer, sempass2, json, xmltree, cgi, typesrenderer
importer, sempass2, json, xmltree, cgi, typesrenderer, astalgo
type
TSections = array[TSymKind, Rope]
@@ -25,9 +25,32 @@ type
indexValFilename: string
analytics: string # Google Analytics javascript, "" if doesn't exist
seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
jArray: JsonNode
types: TStrTable
PDoc* = ref TDocumentor ## Alias to type less.
proc whichType(d: PDoc; n: PNode): PSym =
if n.kind == nkSym:
if d.types.strTableContains(n.sym):
result = n.sym
else:
for i in 0..<safeLen(n):
let x = whichType(d, n[i])
if x != nil: return x
proc attachToType(d: PDoc; p: PSym): PSym =
let params = p.ast.sons[paramsPos]
# first check the first parameter, then the return type,
# then the other parameter:
template check(i) =
result = whichType(d, params[i])
if result != nil: return result
if params.len > 1: check(1)
if params.len > 0: check(0)
for i in 2..<params.len: check(i)
proc compilerMsgHandler(filename: string, line, col: int,
msgKind: rst.MsgKind, arg: string) {.procvar.} =
# translate msg kind:
@@ -81,6 +104,8 @@ proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
result.seenSymbols = newStringTable(modeCaseInsensitive)
result.id = 100
result.jArray = newJArray()
initStrTable result.types
proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) =
if gCmd != cmdRst2tex: addf(dest, xml, args)
@@ -226,10 +251,27 @@ proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
result = esc(d.target, "`")
for i in 0.. <n.len: result.add(getName(d, n[i], splitAfter))
result.add esc(d.target, "`")
of nkOpenSymChoice, nkClosedSymChoice:
result = getName(d, n[0], splitAfter)
else:
internalError(n.info, "getName()")
result = ""
proc getNameIdent(n: PNode): PIdent =
case n.kind
of nkPostfix: result = getNameIdent(n.sons[1])
of nkPragmaExpr: result = getNameIdent(n.sons[0])
of nkSym: result = n.sym.name
of nkIdent: result = n.ident
of nkAccQuoted:
var r = ""
for i in 0.. <n.len: r.add(getNameIdent(n[i]).s)
result = getIdent(r)
of nkOpenSymChoice, nkClosedSymChoice:
result = getNameIdent(n[0])
else:
result = nil
proc getRstName(n: PNode): PRstNode =
case n.kind
of nkPostfix: result = getRstName(n.sons[1])
@@ -239,6 +281,8 @@ proc getRstName(n: PNode): PRstNode =
of nkAccQuoted:
result = getRstName(n.sons[0])
for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text)
of nkOpenSymChoice, nkClosedSymChoice:
result = getRstName(n[0])
else:
internalError(n.info, "getRstName()")
result = nil
@@ -395,6 +439,12 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr:
dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
[rope(esc(d.target, literal))])
if k in routineKinds and nameNode.kind == nkSym:
let att = attachToType(d, nameNode.sym)
if att != nil:
dispA(result, """<span class="attachedType" style="visibility:hidden">$1</span>""", "",
[rope esc(d.target, att.name.s)])
inc(d.id)
let
plainNameRope = rope(xmltree.escape(plainName.strip))
@@ -438,8 +488,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
setIndexTerm(d[], symbolOrId, name, linkTitle,
xmltree.escape(plainDocstring.docstringSummary))
if k == skType and nameNode.kind == nkSym:
d.types.strTableAdd nameNode.sym
proc genJSONItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
proc genJsonItem(d: PDoc, n, nameNode: PNode, k: TSymKind): JsonNode =
if not isVisible(nameNode): return
var
name = getName(d, nameNode)
@@ -499,46 +551,44 @@ proc generateDoc*(d: PDoc, n: PNode) =
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
else: discard
proc generateJson(d: PDoc, n: PNode, jArray: JsonNode = nil): JsonNode =
proc add(d: PDoc; j: JsonNode) =
if j != nil: d.jArray.add j
proc generateJson*(d: PDoc, n: PNode) =
case n.kind
of nkCommentStmt:
if n.comment != nil and startsWith(n.comment, "##"):
let stripped = n.comment.substr(2).strip
result = %{ "comment": %stripped }
d.add %{ "comment": %stripped }
of nkProcDef:
when useEffectSystem: documentRaises(n)
result = genJSONItem(d, n, n.sons[namePos], skProc)
d.add genJsonItem(d, n, n.sons[namePos], skProc)
of nkMethodDef:
when useEffectSystem: documentRaises(n)
result = genJSONItem(d, n, n.sons[namePos], skMethod)
d.add genJsonItem(d, n, n.sons[namePos], skMethod)
of nkIteratorDef:
when useEffectSystem: documentRaises(n)
result = genJSONItem(d, n, n.sons[namePos], skIterator)
d.add genJsonItem(d, n, n.sons[namePos], skIterator)
of nkMacroDef:
result = genJSONItem(d, n, n.sons[namePos], skMacro)
d.add genJsonItem(d, n, n.sons[namePos], skMacro)
of nkTemplateDef:
result = genJSONItem(d, n, n.sons[namePos], skTemplate)
d.add genJsonItem(d, n, n.sons[namePos], skTemplate)
of nkConverterDef:
when useEffectSystem: documentRaises(n)
result = genJSONItem(d, n, n.sons[namePos], skConverter)
d.add genJsonItem(d, n, n.sons[namePos], skConverter)
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
for i in countup(0, sonsLen(n) - 1):
if n.sons[i].kind != nkCommentStmt:
# order is always 'type var let const':
result = genJSONItem(d, n.sons[i], n.sons[i].sons[0],
d.add genJsonItem(d, n.sons[i], n.sons[i].sons[0],
succ(skType, ord(n.kind)-ord(nkTypeSection)))
of nkStmtList:
result = if jArray != nil: jArray else: newJArray()
for i in countup(0, sonsLen(n) - 1):
var r = generateJson(d, n.sons[i], result)
if r != nil:
result.add(r)
generateJson(d, n.sons[i])
of nkWhenStmt:
# generate documentation for the first branch only:
if not checkForFalse(n.sons[0].sons[0]) and jArray != nil:
discard generateJson(d, lastSon(n.sons[0]), jArray)
if not checkForFalse(n.sons[0].sons[0]):
generateJson(d, lastSon(n.sons[0]))
else: discard
proc genSection(d: PDoc, kind: TSymKind) =
@@ -607,6 +657,19 @@ proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
else:
writeRope(content, getOutFile(filename, outExt), useWarning)
proc writeOutputJson*(d: PDoc, filename, outExt: string,
useWarning = false) =
let content = $d.jArray
if optStdout in gGlobalOptions:
write(stdout, content)
else:
var f: File
if open(f, getOutFile(filename, outExt), fmWrite):
write(f, content)
close(f)
else:
discard "fixme: error report"
proc commandDoc*() =
var ast = parseFile(gProjectMainIdx)
if ast == nil: return
@@ -636,13 +699,14 @@ proc commandRst2TeX*() =
splitter = "\\-"
commandRstAux(gProjectFull, TexExt)
proc commandJSON*() =
proc commandJson*() =
var ast = parseFile(gProjectMainIdx)
if ast == nil: return
var d = newDocumentor(gProjectFull, options.gConfigVars)
d.hasToc = true
var json = generateJson(d, ast)
var content = rope(pretty(json))
generateJson(d, ast)
let json = d.jArray
let content = rope(pretty(json))
if optStdout in gGlobalOptions:
writeRope(stdout, content)

View File

@@ -29,11 +29,26 @@ proc close(p: PPassContext, n: PNode): PNode =
except IOError:
discard
proc closeJson(p: PPassContext, n: PNode): PNode =
var g = PGen(p)
let useWarning = sfMainModule notin g.module.flags
if gWholeProject or sfMainModule in g.module.flags:
writeOutputJson(g.doc, g.module.filename, ".json", useWarning)
try:
generateIndex(g.doc)
except IOError:
discard
proc processNode(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
generateDoc(g.doc, n)
proc processNodeJson(c: PPassContext, n: PNode): PNode =
result = n
var g = PGen(c)
generateJson(g.doc, n)
proc myOpen(module: PSym): PPassContext =
var g: PGen
new(g)
@@ -44,6 +59,8 @@ proc myOpen(module: PSym): PPassContext =
result = g
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
const docgen2JsonPass* = makePass(open = myOpen, process = processNodeJson,
close = closeJson)
proc finishDoc2Pass*(project: string) =
discard

View File

@@ -754,7 +754,7 @@ proc callCCompiler*(projectfile: string) =
"lib", quoteShell(libpath)])
if optCompileOnly notin gGlobalOptions:
execExternalProgram(linkCmd,
if gVerbosity > 1: hintExecuting else: hintLinking)
if optListCmd in gGlobalOptions or gVerbosity > 1: hintExecuting else: hintLinking)
else:
linkCmd = ""
if optGenScript in gGlobalOptions:

View File

@@ -48,6 +48,7 @@ type
etyNull, # null type
etyProc, # proc type
etyBool, # bool type
etySeq, # Nim seq or string type
etyInt, # JavaScript's int
etyFloat, # JavaScript's float
etyString, # JavaScript's string
@@ -156,15 +157,18 @@ proc mapType(typ: PType): TJSTypeKind =
of tyBool: result = etyBool
of tyFloat..tyFloat128: result = etyFloat
of tySet: result = etyObject # map a set to a table
of tyString, tySequence: result = etyInt # little hack to get right semantics
of tyString, tySequence: result = etySeq
of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum,
tyVarargs:
result = etyObject
of tyNil: result = etyNull
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses, tyVoid:
tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid:
result = etyNone
of tyStatic:
if t.n != nil: result = mapType(lastSon t)
else: result = etyNone
of tyProc: result = etyProc
of tyCString: result = etyString
@@ -817,7 +821,7 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
addf(p.body, "$#[$#] = chr($#);$n", [a.rdLoc, b.rdLoc, c.rdLoc])
return
let xtyp = mapType(p, x.typ)
var xtyp = mapType(p, x.typ)
if x.kind == nkHiddenDeref and x.sons[0].kind == nkCall and xtyp != etyObject:
gen(p, x.sons[0], a)
@@ -829,7 +833,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
gen(p, y, b)
# we don't care if it's an etyBaseIndex (global) of a string, it's
# still a string that needs to be copied properly:
if x.typ.skipTypes(abstractInst).kind in {tySequence, tyString}:
xtyp = etySeq
case xtyp
of etySeq:
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
else:
useMagic(p, "nimCopy")
addf(p.body, "$1 = nimCopy(null, $2, $3);$n",
[a.rdLoc, b.res, genTypeInfo(p, y.typ)])
of etyObject:
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
@@ -1049,6 +1064,8 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
of nkObjDownConv:
gen(p, n.sons[0], r)
of nkHiddenDeref:
gen(p, n.sons[0].sons[0], r)
else: internalError(n.sons[0].info, "genAddr: " & $n.sons[0].kind)
proc thisParam(p: PProc; typ: PType): PType =
@@ -1221,6 +1238,7 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
r: var TCompRes) =
var i = 0
var j = 1
r.kind = resExpr
while i < pat.len:
case pat[i]
of '@':
@@ -1234,10 +1252,18 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
genOtherArg(p, n, j, typ, generated, r)
inc j
inc i
of '\31':
# unit separator
add(r.res, "#")
inc i
of '\29':
# group separator
add(r.res, "@")
inc i
else:
let start = i
while i < pat.len:
if pat[i] notin {'@', '#'}: inc(i)
if pat[i] notin {'@', '#', '\31', '\29'}: inc(i)
else: break
if i - 1 >= start:
add(r.res, substr(pat, start, i - 1))
@@ -1404,6 +1430,12 @@ proc createVar(p: PProc, typ: PType, indirect: bool): Rope =
result = putToSeq("null", indirect)
of tySequence, tyString, tyCString, tyPointer, tyProc:
result = putToSeq("null", indirect)
of tyStatic:
if t.n != nil:
result = createVar(p, lastSon t, indirect)
else:
internalError("createVar: " & $t.kind)
result = nil
else:
internalError("createVar: " & $t.kind)
result = nil
@@ -1419,7 +1451,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
discard mangleName(v, p.target)
gen(p, n, a)
case mapType(p, v.typ)
of etyObject:
of etyObject, etySeq:
if needsNoCopy(p, n):
s = a.res
else:

View File

@@ -165,4 +165,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
of tyEnum: genEnumInfo(p, t, result)
of tyObject: genObjectInfo(p, t, result)
of tyTuple: genTupleInfo(p, t, result)
of tyStatic:
if t.n != nil: result = genTypeInfo(p, lastSon t)
else: internalError("genTypeInfo(" & $t.kind & ')')
else: internalError("genTypeInfo(" & $t.kind & ')')

View File

@@ -735,7 +735,8 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
if c == '\226' and
buf[pos+1] == '\128' and
buf[pos+2] == '\147': # It's a 'magic separator' en-dash Unicode
if buf[pos + magicIdentSeparatorRuneByteWidth] notin SymChars:
if buf[pos + magicIdentSeparatorRuneByteWidth] notin SymChars or
isMagicIdentSeparatorRune(buf, pos+magicIdentSeparatorRuneByteWidth) or pos == L.bufpos:
lexMessage(L, errInvalidToken, "")
break
inc(pos, magicIdentSeparatorRuneByteWidth)
@@ -747,7 +748,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
h = h !& ord(c)
inc(pos)
of '_':
if buf[pos+1] notin SymChars:
if buf[pos+1] notin SymChars or isMagicIdentSeparatorRune(buf, pos+1):
lexMessage(L, errInvalidToken, "_")
break
inc(pos)
@@ -1056,7 +1057,8 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
inc(L.bufpos)
of '_':
inc(L.bufpos)
if L.buf[L.bufpos] notin SymChars:
if L.buf[L.bufpos] notin SymChars+{'_'} and not
isMagicIdentSeparatorRune(L.buf, L.bufpos):
tok.tokType = tkSymbol
tok.ident = getIdent("_")
else:
@@ -1077,6 +1079,9 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
tok.tokType = tkCharLit
of '0'..'9':
getNumber(L, tok)
let c = L.buf[L.bufpos]
if c in SymChars+{'_'}:
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
else:
if c in OpChars:
getOperator(L, tok)

View File

@@ -46,10 +46,11 @@ proc commandCheck =
rodPass()
compileProject()
proc commandDoc2 =
proc commandDoc2(json: bool) =
msgs.gErrorMax = high(int) # do not stop after first error
semanticPasses()
registerPass(docgen2Pass)
if json: registerPass(docgen2JsonPass)
else: registerPass(docgen2Pass)
#registerPass(cleanupPass())
compileProject()
finishDoc2Pass(gProjectName)
@@ -281,7 +282,7 @@ proc mainCommand* =
gCmd = cmdDoc
loadConfigs(DocConfig)
defineSymbol("nimdoc")
commandDoc2()
commandDoc2(false)
of "rst2html":
gCmd = cmdRst2html
loadConfigs(DocConfig)
@@ -296,7 +297,13 @@ proc mainCommand* =
loadConfigs(DocConfig)
wantMainModule()
defineSymbol("nimdoc")
commandJSON()
commandJson()
of "jsondoc2":
gCmd = cmdDoc
loadConfigs(DocConfig)
wantMainModule()
defineSymbol("nimdoc")
commandDoc2(true)
of "buildindex":
gCmd = cmdDoc
loadConfigs(DocConfig)

View File

@@ -105,12 +105,13 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile =
resetModule(fileIdx)
return Yes
if gMemCacheData[fileIdx].needsRecompile != Maybe:
return gMemCacheData[fileIdx].needsRecompile
# cycle detection: We claim that a cycle does no harm.
if gMemCacheData[fileIdx].needsRecompile == Probing:
return No
#return gMemCacheData[fileIdx].needsRecompile
if optForceFullMake in gGlobalOptions or
hashChanged(fileIdx):
markDirty
if optForceFullMake in gGlobalOptions or hashChanged(fileIdx):
markDirty()
if gMemCacheData[fileIdx].deps != nil:
gMemCacheData[fileIdx].needsRecompile = Probing
@@ -118,7 +119,7 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile =
let d = checkDepMem(dep)
if d in {Yes, Recompiled}:
# echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d
markDirty
markDirty()
gMemCacheData[fileIdx].needsRecompile = No
return No

View File

@@ -518,7 +518,6 @@ const
warnGcUnsafe,
hintPath,
hintDependency,
hintExecuting,
hintCodeBegin, hintCodeEnd,
hintSource, hintStackTrace,
hintGCStats},
@@ -530,7 +529,7 @@ const
var
ForeignPackageNotes*: TNoteKinds = {hintProcessing, warnUnknownMagic,
hintQuitCalled}
hintQuitCalled, hintExecuting}
filenameToIndexTbl = initTable[string, int32]()
fileInfos*: seq[TFileInfo] = @[]
systemFileIdx*: int32
@@ -621,6 +620,7 @@ var
gHintCounter*: int = 0
gWarnCounter*: int = 0
gErrorMax*: int = 1 # stop after gErrorMax errors
gMainPackageNotes*: TNoteKinds = NotesVerbosity[1]
proc unknownLineInfo*(): TLineInfo =
result.line = int16(-1)

View File

@@ -151,6 +151,7 @@ const
var
gConfigVars* = newStringTable(modeStyleInsensitive)
gDllOverrides = newStringTable(modeCaseInsensitive)
gModuleOverrides* = newStringTable(modeStyleInsensitive)
gPrefixDir* = "" # Overrides the default prefix dir in getPrefixDir proc.
libpath* = ""
gProjectName* = "" # holds a name like 'nim'
@@ -374,6 +375,13 @@ proc rawFindFile2(f: string): string =
it = PStrEntry(it.next)
result = ""
template patchModule() {.dirty.} =
if result.len > 0 and gModuleOverrides.len > 0:
let key = getPackageName(result) & "_" & splitFile(result).name
if gModuleOverrides.hasKey(key):
let ov = gModuleOverrides[key]
if ov.len > 0: result = ov
proc findFile*(f: string): string {.procvar.} =
if f.isAbsolute:
result = if f.existsFile: f else: ""
@@ -385,6 +393,7 @@ proc findFile*(f: string): string {.procvar.} =
result = f.rawFindFile2
if result.len == 0:
result = f.toLower.rawFindFile2
patchModule()
proc findModule*(modulename, currentModule: string): string =
# returns path to module
@@ -403,6 +412,7 @@ proc findModule*(modulename, currentModule: string): string =
result = currentPath / m
if not existsFile(result):
result = findFile(m)
patchModule()
proc libCandidates*(s: string, dest: var seq[string]) =
var le = strutils.find(s, '(')

View File

@@ -13,7 +13,7 @@
import
ast, modules, passes, passaux, condsyms,
options, nimconf, lists, sem, semdata, llstream, vm, vmdef, commands, msgs,
os, times, osproc, wordrecg
os, times, osproc, wordrecg, strtabs
# we support 'cmpIgnoreStyle' natively for efficiency:
from strutils import cmpIgnoreStyle
@@ -122,6 +122,12 @@ proc setupVM*(module: PSym; scriptName: string): PEvalContext =
cbconf warningImpl:
processSpecificNote(a.getString 0, wWarning, passPP, unknownLineInfo(),
a.getString 1)
cbconf patchFile:
let key = a.getString(0) & "_" & a.getString(1)
var val = a.getString(2).addFileExt(NimExt)
if not isAbsolute(val):
val = vthisDir / val
gModuleOverrides[key] = val
proc runNimScript*(scriptName: string; freshDefines=true) =
passes.gIncludeFile = includeModule

View File

@@ -1065,8 +1065,11 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
result = newSymNode(s, n.info)
result.typ = makeTypeDesc(c, s.typ)
of skField:
if c.p != nil and c.p.selfSym != nil:
var ty = skipTypes(c.p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
var p = c.p
while p != nil and p.selfSym == nil:
p = p.next
if p != nil and p.selfSym != nil:
var ty = skipTypes(p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
var check: PNode = nil
if ty.kind == tyObject:
@@ -1079,7 +1082,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
markUsed(n.info, f)
styleCheckUse(n.info, f)
result = newNodeIT(nkDotExpr, n.info, f.typ)
result.add makeDeref(newSymNode(c.p.selfSym))
result.add makeDeref(newSymNode(p.selfSym))
result.add newSymNode(f) # we now have the correct field
if check != nil:
check.sons[0] = result

View File

@@ -411,6 +411,13 @@ proc semUsing(c: PContext; n: PNode): PNode =
if a.sons[length-1].kind != nkEmpty:
localError(a.info, "'using' sections cannot contain assignments")
proc hasEmpty(typ: PType): bool =
if typ.kind in {tySequence, tyArray, tySet}:
result = typ.lastSon.kind == tyEmpty
elif typ.kind == tyTuple:
for s in typ.sons:
result = result or hasEmpty(s)
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
var b: PNode
result = copyNode(n)
@@ -445,8 +452,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
#changeType(def.skipConv, typ, check=true)
else:
typ = skipIntLit(def.typ)
if typ.kind in {tySequence, tyArray, tySet} and
typ.lastSon.kind == tyEmpty:
if hasEmpty(typ):
localError(def.info, errCannotInferTypeOfTheLiteral,
($typ.kind).substr(2).toLower)
else:

View File

@@ -1746,8 +1746,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
if formal.ast == nil:
if formal.typ.kind == tyVarargs:
var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ,
container, m, c))
setSon(m.call, formal.position + 1,
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
else:
# no default value
m.state = csNoMatch

View File

@@ -541,7 +541,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
else:
result.add typeToString(t.sons[0])
of tyRange:
result = "range " & rangeToStr(t.n)
result = "range "
if t.n != nil and t.n.kind == nkRange:
result.add rangeToStr(t.n)
if prefer != preferExported:
result.add("(" & typeToString(t.sons[0]) & ")")
of tyProc:
@@ -1315,6 +1317,9 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
of tyTypeDesc:
result = computeSizeAux(typ.base, a)
of tyForward: return szIllegalRecursion
of tyStatic:
if typ.n != nil: result = computeSizeAux(lastSon(typ), a)
else: result = szUnknownSize
else:
#internalError("computeSizeAux()")
result = szUnknownSize

View File

@@ -1686,10 +1686,10 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
of skType:
genTypeLit(c, s.typ, dest)
of skGenericParam:
if c.prc.sym.kind == skMacro:
if c.prc.sym != nil and c.prc.sym.kind == skMacro:
genRdVar(c, n, dest, flags)
else:
internalError(n.info, "cannot generate code for: " & s.name.s)
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
else:
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
of nkCallKinds:

View File

@@ -23,10 +23,6 @@ arm.linux.gcc.linkerexe = "arm-linux-gcc"
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
mips.linux.gcc.linkerexe = "mips-openwrt-linux-gcc"
@if not nimfix:
cs:partial
@end
path="$lib/deprecated/core"
path="$lib/deprecated/pure"
path="$lib/pure/collections"
@@ -168,10 +164,5 @@ vcc.options.always = "/nologo"
vcc.options.speed = "/O2 /arch:SSE2"
vcc.options.size = "/O1"
# Configuration for the Digital Mars C/C++ compiler:
@if windows:
dmc.path = r"$nimrod\dist\dm\bin"
@end
# Configuration for the Tiny C Compiler:
tcc.options.always = "-w"

View File

@@ -6,6 +6,7 @@ Advanced commands:
//rst2html convert a reStructuredText file to HTML
//rst2tex convert a reStructuredText file to TeX
//jsondoc extract the documentation to a json file
//jsondoc2 extract documentation to a json file (uses doc2)
//buildIndex build an index for the whole documentation
//run run the project (with Tiny C backend; buggy!)
//genDepend generate a DOT file containing the

View File

@@ -152,11 +152,13 @@ proc add*[T](q: var Queue[T], item: T) =
q.data[q.wr] = item
q.wr = (q.wr + 1) and q.mask
proc default[T](t: typedesc[T]): T {.inline.} = discard
proc pop*[T](q: var Queue[T]): T {.inline, discardable.} =
## Remove and returns the first (oldest) element of the queue `q`.
emptyCheck(q)
dec q.count
result = q.data[q.rd]
q.data[q.rd] = default(type(result))
q.rd = (q.rd + 1) and q.mask
proc enqueue*[T](q: var Queue[T], item: T) =

View File

@@ -16,6 +16,39 @@
## semantics, this means that ``=`` performs a copy of the hash table.
## For **reference** semantics use the ``Ref`` variant: ``TableRef``,
## ``OrderedTableRef``, ``CountTableRef``.
## To give an example, when `a` is a Table, then `var b = a` gives `b`
## as a new independent table. b is initialised with the contents of `a`.
## Changing `b` does not affect `a` and vice versa:
##
## .. code-block::
## import tables
##
## var
## a = {1: "one", 2: "two"}.toTable # creates a Table
## b = a
##
## echo a, b # output: {1: one, 2: two}{1: one, 2: two}
##
## b[3] = "three"
## echo a, b # output: {1: one, 2: two}{1: one, 2: two, 3: three}
## echo a == b # output: false
##
## On the other hand, when `a` is a TableRef instead, then changes to `b` also affect `a`.
## Both `a` and `b` reference the same data structure:
##
## .. code-block::
## import tables
##
## var
## a = {1: "one", 2: "two"}.newTable # creates a TableRef
## b = a
##
## echo a, b # output: {1: one, 2: two}{1: one, 2: two}
##
## b[3] = "three"
## echo a, b # output: {1: one, 2: two, 3: three}{1: one, 2: two, 3: three}
## echo a == b # output: true
##
##
## If you are using simple standard types like ``int`` or ``string`` for the
## keys of the table you won't have any problems, but as soon as you try to use

View File

@@ -1127,7 +1127,7 @@ proc parseJson(p: var JsonParser): JsonNode =
discard getTok(p)
while p.tok != tkCurlyRi:
if p.tok != tkString:
raiseParseErr(p, "string literal as key expected")
raiseParseErr(p, "string literal as key")
var key = p.a
discard getTok(p)
eat(p, tkColon)

View File

@@ -452,10 +452,13 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
# now it is buffered in the ZCT
res.typ = typ
when leakDetector and not hasThreadSupport:
if framePtr != nil and framePtr.prev != nil:
res.filename = framePtr.prev.filename
res.line = framePtr.prev.line
when leakDetector:
res.filename = nil
res.line = 0
when not hasThreadSupport:
if framePtr != nil and framePtr.prev != nil:
res.filename = framePtr.prev.filename
res.line = framePtr.prev.line
# refcount is zero, color is black, but mark it to be in the ZCT
res.refcount = ZctFlag
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
@@ -503,10 +506,13 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
# now it is buffered in the ZCT
res.typ = typ
when leakDetector and not hasThreadSupport:
if framePtr != nil and framePtr.prev != nil:
res.filename = framePtr.prev.filename
res.line = framePtr.prev.line
when leakDetector:
res.filename = nil
res.line = 0
when not hasThreadSupport:
if framePtr != nil and framePtr.prev != nil:
res.filename = framePtr.prev.filename
res.line = framePtr.prev.line
res.refcount = rcIncrement # refcount is 1
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
when logGC: writeCell("new cell", res)

View File

@@ -65,6 +65,21 @@ proc hint*(name: string; val: bool) =
let v = if val: "on" else: "off"
hintImpl(name & "]:" & v, "hint[" & name & "]:" & v)
proc patchFile*(package, filename, replacement: string) =
## Overrides the location of a given file belonging to the
## passed package.
## If the ``replacement`` is not an absolute path, the path
## is interpreted to be local to the Nimscript file that contains
## the call to ``patchFile``, Nim's ``--path`` is not used at all
## to resolve the filename!
##
## Example:
##
## .. code-block:: nim
##
## patchFile("stdlib", "asyncdispatch", "patches/replacement")
discard
proc getCommand*(): string =
## Gets the Nim command that the compiler has been invoked with, for example
## "c", "js", "build", "help".

View File

@@ -0,0 +1,11 @@
discard """
output: '''true'''
"""
# bug #4471
when true:
let s1 = "123"
var s2 = s1
s2.setLen(0)
# fails - s1.len == 0
echo s1.len == 3

View File

@@ -0,0 +1,20 @@
discard """
output: '''1 mod 7'''
"""
# bug #3706
type Modulo[M: static[int]] = distinct int
proc modulo(a: int, M: static[int]): Modulo[M] = Modulo[M](a %% M)
proc `+`[M: static[int]](a, b: Modulo[M]): Modulo[M] = (a.int + b.int).modulo(M)
proc `$`*[M: static[int]](a: Modulo[M]): string = $(a.int) & " mod " & $(M)
when isMainModule:
let
a = 3.modulo(7)
b = 5.modulo(7)
echo a + b

View File

@@ -0,0 +1,4 @@
proc ln*(x: float): float =
return 0.5

View File

@@ -1,10 +1,12 @@
discard """
cmd: "nim default $file"
output: '''hello world!'''
output: '''hello world! 0.5'''
msg: '''[NimScript] exec: gcc -v'''
"""
when not defined(definedefine):
{.fatal: "wrong nim script configuration".}
echo "hello world!"
import math
echo "hello world! ", ln 2.0

View File

@@ -10,6 +10,8 @@ import ospaths
warning("uninit", off)
hint("processing", off)
#--verbosity:2
patchFile("stdlib", "math", "mymath")
task listDirs, "lists every subdirectory":
for x in listDirs("."):

View File

@@ -0,0 +1,6 @@
# Bug: https://github.com/nim-lang/Nim/issues/4475
# Fix: https://github.com/nim-lang/Nim/pull/4477
proc test(x: varargs[string], y: int) = discard
test(y = 1)

View File

@@ -0,0 +1,11 @@
discard """
file: "tassignemptytuple.nim"
line: 11
errormsg: "cannot infer the type of the tuple"
"""
var
foo: seq[int]
bar: tuple[a: seq[int], b: set[char]]
(foo, bar) = (@[], (@[], {}))

View File

@@ -49,6 +49,16 @@ Compiler Additions
- The ``-d/--define`` flag can now optionally take a value to be used
by code at compile time.
Nimscript Additions
-------------------
- Finally it's possible to dis/enable specific hints and warnings in
Nimscript via the procs ``warning`` and ``hint``.
- Nimscript exports a proc named ``patchFile`` which can be used to
patch modules or include files for different Nimble packages, including
the ``stdlib`` package.
Language Additions
------------------