mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 & ')')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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, '(')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) =
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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".
|
||||
|
||||
11
tests/js/tstring_assignment.nim
Normal file
11
tests/js/tstring_assignment.nim
Normal 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
|
||||
20
tests/metatype/tmodulo.nim
Normal file
20
tests/metatype/tmodulo.nim
Normal 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
|
||||
|
||||
4
tests/newconfig/mymath.nim
Normal file
4
tests/newconfig/mymath.nim
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
proc ln*(x: float): float =
|
||||
return 0.5
|
||||
@@ -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
|
||||
|
||||
@@ -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("."):
|
||||
|
||||
6
tests/overload/tissue4475.nim
Normal file
6
tests/overload/tissue4475.nim
Normal 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)
|
||||
11
tests/types/tassignemptytuple.nim
Normal file
11
tests/types/tassignemptytuple.nim
Normal 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) = (@[], (@[], {}))
|
||||
@@ -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
|
||||
------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user