Merge branch 'devel' of github.com:nim-lang/Nim into devel
This commit is contained in:
commit
928ac1e994
34 changed files with 361 additions and 75 deletions
|
|
@ -965,7 +965,6 @@ const
|
||||||
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
|
var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
|
||||||
var
|
var
|
||||||
gMainPackageId*: int
|
gMainPackageId*: int
|
||||||
gMainPackageNotes*: TNoteKinds
|
|
||||||
|
|
||||||
proc isCallExpr*(n: PNode): bool =
|
proc isCallExpr*(n: PNode): bool =
|
||||||
result = n.kind in nkCallKinds
|
result = n.kind in nkCallKinds
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,9 @@ proc mapType(typ: PType): TCTypeKind =
|
||||||
of tyCString: result = ctCString
|
of tyCString: result = ctCString
|
||||||
of tyInt..tyUInt64:
|
of tyInt..tyUInt64:
|
||||||
result = TCTypeKind(ord(typ.kind) - ord(tyInt) + ord(ctInt))
|
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")
|
else: internalError("mapType")
|
||||||
|
|
||||||
proc mapReturnType(typ: PType): TCTypeKind =
|
proc mapReturnType(typ: PType): TCTypeKind =
|
||||||
|
|
@ -256,6 +259,11 @@ proc getSimpleTypeDesc(m: BModule, typ: PType): Rope =
|
||||||
of tyInt..tyUInt64:
|
of tyInt..tyUInt64:
|
||||||
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.kind])
|
result = typeNameOrLiteral(typ, NumericalTypeToStr[typ.kind])
|
||||||
of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.sons[0])
|
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
|
else: result = nil
|
||||||
|
|
||||||
proc pushType(m: BModule, typ: PType) =
|
proc pushType(m: BModule, typ: PType) =
|
||||||
|
|
@ -1025,6 +1033,9 @@ proc genTypeInfo(m: BModule, t: PType): Rope =
|
||||||
of tyEmpty, tyVoid: result = rope"0"
|
of tyEmpty, tyVoid: result = rope"0"
|
||||||
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
|
of tyPointer, tyBool, tyChar, tyCString, tyString, tyInt..tyUInt64, tyVar:
|
||||||
genTypeInfoAuxBase(m, t, t, result, rope"0")
|
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:
|
of tyProc:
|
||||||
if t.callConv != ccClosure:
|
if t.callConv != ccClosure:
|
||||||
genTypeInfoAuxBase(m, t, t, result, rope"0")
|
genTypeInfoAuxBase(m, t, t, result, rope"0")
|
||||||
|
|
|
||||||
|
|
@ -181,9 +181,11 @@ proc processSpecificNote*(arg: string, state: TSpecialWord, pass: TCmdLinePass,
|
||||||
case whichKeyword(substr(arg, i))
|
case whichKeyword(substr(arg, i))
|
||||||
of wOn:
|
of wOn:
|
||||||
incl(gNotes, n)
|
incl(gNotes, n)
|
||||||
|
incl(gMainPackageNotes, n)
|
||||||
incl(enableNotes, n)
|
incl(enableNotes, n)
|
||||||
of wOff:
|
of wOff:
|
||||||
excl(gNotes, n)
|
excl(gNotes, n)
|
||||||
|
excl(gMainPackageNotes, n)
|
||||||
incl(disableNotes, n)
|
incl(disableNotes, n)
|
||||||
excl(ForeignPackageNotes, n)
|
excl(ForeignPackageNotes, n)
|
||||||
else: localError(info, errOnOrOffExpectedButXFound, arg)
|
else: localError(info, errOnOrOffExpectedButXFound, arg)
|
||||||
|
|
@ -548,6 +550,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo) =
|
||||||
gNotes = NotesVerbosity[gVerbosity]
|
gNotes = NotesVerbosity[gVerbosity]
|
||||||
incl(gNotes, enableNotes)
|
incl(gNotes, enableNotes)
|
||||||
excl(gNotes, disableNotes)
|
excl(gNotes, disableNotes)
|
||||||
|
gMainPackageNotes = gNotes
|
||||||
of "parallelbuild":
|
of "parallelbuild":
|
||||||
expectArg(switch, arg, pass, info)
|
expectArg(switch, arg, pass, info)
|
||||||
gNumberOfProcessors = parseInt(arg)
|
gNumberOfProcessors = parseInt(arg)
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
import
|
import
|
||||||
ast, strutils, strtabs, options, msgs, os, ropes, idents,
|
ast, strutils, strtabs, options, msgs, os, ropes, idents,
|
||||||
wordrecg, syntaxes, renderer, lexer, rstast, rst, rstgen, times, highlite,
|
wordrecg, syntaxes, renderer, lexer, rstast, rst, rstgen, times, highlite,
|
||||||
importer, sempass2, json, xmltree, cgi, typesrenderer
|
importer, sempass2, json, xmltree, cgi, typesrenderer, astalgo
|
||||||
|
|
||||||
type
|
type
|
||||||
TSections = array[TSymKind, Rope]
|
TSections = array[TSymKind, Rope]
|
||||||
|
|
@ -25,9 +25,32 @@ type
|
||||||
indexValFilename: string
|
indexValFilename: string
|
||||||
analytics: string # Google Analytics javascript, "" if doesn't exist
|
analytics: string # Google Analytics javascript, "" if doesn't exist
|
||||||
seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
|
seenSymbols: StringTableRef # avoids duplicate symbol generation for HTML.
|
||||||
|
jArray: JsonNode
|
||||||
|
types: TStrTable
|
||||||
|
|
||||||
PDoc* = ref TDocumentor ## Alias to type less.
|
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,
|
proc compilerMsgHandler(filename: string, line, col: int,
|
||||||
msgKind: rst.MsgKind, arg: string) {.procvar.} =
|
msgKind: rst.MsgKind, arg: string) {.procvar.} =
|
||||||
# translate msg kind:
|
# translate msg kind:
|
||||||
|
|
@ -81,6 +104,8 @@ proc newDocumentor*(filename: string, config: StringTableRef): PDoc =
|
||||||
|
|
||||||
result.seenSymbols = newStringTable(modeCaseInsensitive)
|
result.seenSymbols = newStringTable(modeCaseInsensitive)
|
||||||
result.id = 100
|
result.id = 100
|
||||||
|
result.jArray = newJArray()
|
||||||
|
initStrTable result.types
|
||||||
|
|
||||||
proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
proc dispA(dest: var Rope, xml, tex: string, args: openArray[Rope]) =
|
||||||
if gCmd != cmdRst2tex: addf(dest, xml, args)
|
if gCmd != cmdRst2tex: addf(dest, xml, args)
|
||||||
|
|
@ -226,10 +251,27 @@ proc getName(d: PDoc, n: PNode, splitAfter = -1): string =
|
||||||
result = esc(d.target, "`")
|
result = esc(d.target, "`")
|
||||||
for i in 0.. <n.len: result.add(getName(d, n[i], splitAfter))
|
for i in 0.. <n.len: result.add(getName(d, n[i], splitAfter))
|
||||||
result.add esc(d.target, "`")
|
result.add esc(d.target, "`")
|
||||||
|
of nkOpenSymChoice, nkClosedSymChoice:
|
||||||
|
result = getName(d, n[0], splitAfter)
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "getName()")
|
internalError(n.info, "getName()")
|
||||||
result = ""
|
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 =
|
proc getRstName(n: PNode): PRstNode =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkPostfix: result = getRstName(n.sons[1])
|
of nkPostfix: result = getRstName(n.sons[1])
|
||||||
|
|
@ -239,6 +281,8 @@ proc getRstName(n: PNode): PRstNode =
|
||||||
of nkAccQuoted:
|
of nkAccQuoted:
|
||||||
result = getRstName(n.sons[0])
|
result = getRstName(n.sons[0])
|
||||||
for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text)
|
for i in 1 .. <n.len: result.text.add(getRstName(n[i]).text)
|
||||||
|
of nkOpenSymChoice, nkClosedSymChoice:
|
||||||
|
result = getRstName(n[0])
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "getRstName()")
|
internalError(n.info, "getRstName()")
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -395,6 +439,12 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||||
tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr:
|
tkGStrLit, tkGTripleStrLit, tkInfixOpr, tkPrefixOpr, tkPostfixOpr:
|
||||||
dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
|
dispA(result, "<span class=\"Other\">$1</span>", "\\spanOther{$1}",
|
||||||
[rope(esc(d.target, literal))])
|
[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)
|
inc(d.id)
|
||||||
let
|
let
|
||||||
plainNameRope = rope(xmltree.escape(plainName.strip))
|
plainNameRope = rope(xmltree.escape(plainName.strip))
|
||||||
|
|
@ -438,8 +488,10 @@ proc genItem(d: PDoc, n, nameNode: PNode, k: TSymKind) =
|
||||||
|
|
||||||
setIndexTerm(d[], symbolOrId, name, linkTitle,
|
setIndexTerm(d[], symbolOrId, name, linkTitle,
|
||||||
xmltree.escape(plainDocstring.docstringSummary))
|
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
|
if not isVisible(nameNode): return
|
||||||
var
|
var
|
||||||
name = getName(d, nameNode)
|
name = getName(d, nameNode)
|
||||||
|
|
@ -499,46 +551,44 @@ proc generateDoc*(d: PDoc, n: PNode) =
|
||||||
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
|
of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
|
||||||
else: discard
|
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
|
case n.kind
|
||||||
of nkCommentStmt:
|
of nkCommentStmt:
|
||||||
if n.comment != nil and startsWith(n.comment, "##"):
|
if n.comment != nil and startsWith(n.comment, "##"):
|
||||||
let stripped = n.comment.substr(2).strip
|
let stripped = n.comment.substr(2).strip
|
||||||
result = %{ "comment": %stripped }
|
d.add %{ "comment": %stripped }
|
||||||
of nkProcDef:
|
of nkProcDef:
|
||||||
when useEffectSystem: documentRaises(n)
|
when useEffectSystem: documentRaises(n)
|
||||||
result = genJSONItem(d, n, n.sons[namePos], skProc)
|
d.add genJsonItem(d, n, n.sons[namePos], skProc)
|
||||||
of nkMethodDef:
|
of nkMethodDef:
|
||||||
when useEffectSystem: documentRaises(n)
|
when useEffectSystem: documentRaises(n)
|
||||||
result = genJSONItem(d, n, n.sons[namePos], skMethod)
|
d.add genJsonItem(d, n, n.sons[namePos], skMethod)
|
||||||
of nkIteratorDef:
|
of nkIteratorDef:
|
||||||
when useEffectSystem: documentRaises(n)
|
when useEffectSystem: documentRaises(n)
|
||||||
result = genJSONItem(d, n, n.sons[namePos], skIterator)
|
d.add genJsonItem(d, n, n.sons[namePos], skIterator)
|
||||||
of nkMacroDef:
|
of nkMacroDef:
|
||||||
result = genJSONItem(d, n, n.sons[namePos], skMacro)
|
d.add genJsonItem(d, n, n.sons[namePos], skMacro)
|
||||||
of nkTemplateDef:
|
of nkTemplateDef:
|
||||||
result = genJSONItem(d, n, n.sons[namePos], skTemplate)
|
d.add genJsonItem(d, n, n.sons[namePos], skTemplate)
|
||||||
of nkConverterDef:
|
of nkConverterDef:
|
||||||
when useEffectSystem: documentRaises(n)
|
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:
|
of nkTypeSection, nkVarSection, nkLetSection, nkConstSection:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
if n.sons[i].kind != nkCommentStmt:
|
if n.sons[i].kind != nkCommentStmt:
|
||||||
# order is always 'type var let const':
|
# 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)))
|
succ(skType, ord(n.kind)-ord(nkTypeSection)))
|
||||||
of nkStmtList:
|
of nkStmtList:
|
||||||
result = if jArray != nil: jArray else: newJArray()
|
|
||||||
|
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var r = generateJson(d, n.sons[i], result)
|
generateJson(d, n.sons[i])
|
||||||
if r != nil:
|
|
||||||
result.add(r)
|
|
||||||
|
|
||||||
of nkWhenStmt:
|
of nkWhenStmt:
|
||||||
# generate documentation for the first branch only:
|
# generate documentation for the first branch only:
|
||||||
if not checkForFalse(n.sons[0].sons[0]) and jArray != nil:
|
if not checkForFalse(n.sons[0].sons[0]):
|
||||||
discard generateJson(d, lastSon(n.sons[0]), jArray)
|
generateJson(d, lastSon(n.sons[0]))
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
proc genSection(d: PDoc, kind: TSymKind) =
|
proc genSection(d: PDoc, kind: TSymKind) =
|
||||||
|
|
@ -607,6 +657,19 @@ proc writeOutput*(d: PDoc, filename, outExt: string, useWarning = false) =
|
||||||
else:
|
else:
|
||||||
writeRope(content, getOutFile(filename, outExt), useWarning)
|
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*() =
|
proc commandDoc*() =
|
||||||
var ast = parseFile(gProjectMainIdx)
|
var ast = parseFile(gProjectMainIdx)
|
||||||
if ast == nil: return
|
if ast == nil: return
|
||||||
|
|
@ -636,13 +699,14 @@ proc commandRst2TeX*() =
|
||||||
splitter = "\\-"
|
splitter = "\\-"
|
||||||
commandRstAux(gProjectFull, TexExt)
|
commandRstAux(gProjectFull, TexExt)
|
||||||
|
|
||||||
proc commandJSON*() =
|
proc commandJson*() =
|
||||||
var ast = parseFile(gProjectMainIdx)
|
var ast = parseFile(gProjectMainIdx)
|
||||||
if ast == nil: return
|
if ast == nil: return
|
||||||
var d = newDocumentor(gProjectFull, options.gConfigVars)
|
var d = newDocumentor(gProjectFull, options.gConfigVars)
|
||||||
d.hasToc = true
|
d.hasToc = true
|
||||||
var json = generateJson(d, ast)
|
generateJson(d, ast)
|
||||||
var content = rope(pretty(json))
|
let json = d.jArray
|
||||||
|
let content = rope(pretty(json))
|
||||||
|
|
||||||
if optStdout in gGlobalOptions:
|
if optStdout in gGlobalOptions:
|
||||||
writeRope(stdout, content)
|
writeRope(stdout, content)
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,26 @@ proc close(p: PPassContext, n: PNode): PNode =
|
||||||
except IOError:
|
except IOError:
|
||||||
discard
|
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 =
|
proc processNode(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
var g = PGen(c)
|
var g = PGen(c)
|
||||||
generateDoc(g.doc, n)
|
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 =
|
proc myOpen(module: PSym): PPassContext =
|
||||||
var g: PGen
|
var g: PGen
|
||||||
new(g)
|
new(g)
|
||||||
|
|
@ -44,6 +59,8 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
result = g
|
result = g
|
||||||
|
|
||||||
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
|
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)
|
||||||
|
const docgen2JsonPass* = makePass(open = myOpen, process = processNodeJson,
|
||||||
|
close = closeJson)
|
||||||
|
|
||||||
proc finishDoc2Pass*(project: string) =
|
proc finishDoc2Pass*(project: string) =
|
||||||
discard
|
discard
|
||||||
|
|
|
||||||
|
|
@ -754,7 +754,7 @@ proc callCCompiler*(projectfile: string) =
|
||||||
"lib", quoteShell(libpath)])
|
"lib", quoteShell(libpath)])
|
||||||
if optCompileOnly notin gGlobalOptions:
|
if optCompileOnly notin gGlobalOptions:
|
||||||
execExternalProgram(linkCmd,
|
execExternalProgram(linkCmd,
|
||||||
if gVerbosity > 1: hintExecuting else: hintLinking)
|
if optListCmd in gGlobalOptions or gVerbosity > 1: hintExecuting else: hintLinking)
|
||||||
else:
|
else:
|
||||||
linkCmd = ""
|
linkCmd = ""
|
||||||
if optGenScript in gGlobalOptions:
|
if optGenScript in gGlobalOptions:
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ type
|
||||||
etyNull, # null type
|
etyNull, # null type
|
||||||
etyProc, # proc type
|
etyProc, # proc type
|
||||||
etyBool, # bool type
|
etyBool, # bool type
|
||||||
|
etySeq, # Nim seq or string type
|
||||||
etyInt, # JavaScript's int
|
etyInt, # JavaScript's int
|
||||||
etyFloat, # JavaScript's float
|
etyFloat, # JavaScript's float
|
||||||
etyString, # JavaScript's string
|
etyString, # JavaScript's string
|
||||||
|
|
@ -156,15 +157,18 @@ proc mapType(typ: PType): TJSTypeKind =
|
||||||
of tyBool: result = etyBool
|
of tyBool: result = etyBool
|
||||||
of tyFloat..tyFloat128: result = etyFloat
|
of tyFloat..tyFloat128: result = etyFloat
|
||||||
of tySet: result = etyObject # map a set to a table
|
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,
|
of tyObject, tyArray, tyArrayConstr, tyTuple, tyOpenArray, tyBigNum,
|
||||||
tyVarargs:
|
tyVarargs:
|
||||||
result = etyObject
|
result = etyObject
|
||||||
of tyNil: result = etyNull
|
of tyNil: result = etyNull
|
||||||
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
|
of tyGenericInst, tyGenericParam, tyGenericBody, tyGenericInvocation,
|
||||||
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
|
tyNone, tyFromExpr, tyForward, tyEmpty, tyFieldAccessor,
|
||||||
tyExpr, tyStmt, tyStatic, tyTypeDesc, tyTypeClasses, tyVoid:
|
tyExpr, tyStmt, tyTypeDesc, tyTypeClasses, tyVoid:
|
||||||
result = etyNone
|
result = etyNone
|
||||||
|
of tyStatic:
|
||||||
|
if t.n != nil: result = mapType(lastSon t)
|
||||||
|
else: result = etyNone
|
||||||
of tyProc: result = etyProc
|
of tyProc: result = etyProc
|
||||||
of tyCString: result = etyString
|
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])
|
addf(p.body, "$#[$#] = chr($#);$n", [a.rdLoc, b.rdLoc, c.rdLoc])
|
||||||
return
|
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:
|
if x.kind == nkHiddenDeref and x.sons[0].kind == nkCall and xtyp != etyObject:
|
||||||
gen(p, x.sons[0], a)
|
gen(p, x.sons[0], a)
|
||||||
|
|
@ -829,7 +833,18 @@ proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
|
||||||
|
|
||||||
gen(p, y, b)
|
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
|
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:
|
of etyObject:
|
||||||
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
if (needsNoCopy(p, y) and needsNoCopy(p, x)) or noCopyNeeded:
|
||||||
addf(p.body, "$1 = $2;$n", [a.rdLoc, b.rdLoc])
|
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 & ')')
|
else: internalError(n.sons[0].info, "expr(nkBracketExpr, " & $kindOfIndexedExpr & ')')
|
||||||
of nkObjDownConv:
|
of nkObjDownConv:
|
||||||
gen(p, n.sons[0], r)
|
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)
|
else: internalError(n.sons[0].info, "genAddr: " & $n.sons[0].kind)
|
||||||
|
|
||||||
proc thisParam(p: PProc; typ: PType): PType =
|
proc thisParam(p: PProc; typ: PType): PType =
|
||||||
|
|
@ -1221,6 +1238,7 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
|
||||||
r: var TCompRes) =
|
r: var TCompRes) =
|
||||||
var i = 0
|
var i = 0
|
||||||
var j = 1
|
var j = 1
|
||||||
|
r.kind = resExpr
|
||||||
while i < pat.len:
|
while i < pat.len:
|
||||||
case pat[i]
|
case pat[i]
|
||||||
of '@':
|
of '@':
|
||||||
|
|
@ -1234,10 +1252,18 @@ proc genPatternCall(p: PProc; n: PNode; pat: string; typ: PType;
|
||||||
genOtherArg(p, n, j, typ, generated, r)
|
genOtherArg(p, n, j, typ, generated, r)
|
||||||
inc j
|
inc j
|
||||||
inc i
|
inc i
|
||||||
|
of '\31':
|
||||||
|
# unit separator
|
||||||
|
add(r.res, "#")
|
||||||
|
inc i
|
||||||
|
of '\29':
|
||||||
|
# group separator
|
||||||
|
add(r.res, "@")
|
||||||
|
inc i
|
||||||
else:
|
else:
|
||||||
let start = i
|
let start = i
|
||||||
while i < pat.len:
|
while i < pat.len:
|
||||||
if pat[i] notin {'@', '#'}: inc(i)
|
if pat[i] notin {'@', '#', '\31', '\29'}: inc(i)
|
||||||
else: break
|
else: break
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
add(r.res, substr(pat, start, i - 1))
|
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)
|
result = putToSeq("null", indirect)
|
||||||
of tySequence, tyString, tyCString, tyPointer, tyProc:
|
of tySequence, tyString, tyCString, tyPointer, tyProc:
|
||||||
result = putToSeq("null", indirect)
|
result = putToSeq("null", indirect)
|
||||||
|
of tyStatic:
|
||||||
|
if t.n != nil:
|
||||||
|
result = createVar(p, lastSon t, indirect)
|
||||||
|
else:
|
||||||
|
internalError("createVar: " & $t.kind)
|
||||||
|
result = nil
|
||||||
else:
|
else:
|
||||||
internalError("createVar: " & $t.kind)
|
internalError("createVar: " & $t.kind)
|
||||||
result = nil
|
result = nil
|
||||||
|
|
@ -1419,7 +1451,7 @@ proc genVarInit(p: PProc, v: PSym, n: PNode) =
|
||||||
discard mangleName(v, p.target)
|
discard mangleName(v, p.target)
|
||||||
gen(p, n, a)
|
gen(p, n, a)
|
||||||
case mapType(p, v.typ)
|
case mapType(p, v.typ)
|
||||||
of etyObject:
|
of etyObject, etySeq:
|
||||||
if needsNoCopy(p, n):
|
if needsNoCopy(p, n):
|
||||||
s = a.res
|
s = a.res
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -165,4 +165,7 @@ proc genTypeInfo(p: PProc, typ: PType): Rope =
|
||||||
of tyEnum: genEnumInfo(p, t, result)
|
of tyEnum: genEnumInfo(p, t, result)
|
||||||
of tyObject: genObjectInfo(p, t, result)
|
of tyObject: genObjectInfo(p, t, result)
|
||||||
of tyTuple: genTupleInfo(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 & ')')
|
else: internalError("genTypeInfo(" & $t.kind & ')')
|
||||||
|
|
|
||||||
|
|
@ -735,7 +735,8 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
if c == '\226' and
|
if c == '\226' and
|
||||||
buf[pos+1] == '\128' and
|
buf[pos+1] == '\128' and
|
||||||
buf[pos+2] == '\147': # It's a 'magic separator' en-dash Unicode
|
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, "–")
|
lexMessage(L, errInvalidToken, "–")
|
||||||
break
|
break
|
||||||
inc(pos, magicIdentSeparatorRuneByteWidth)
|
inc(pos, magicIdentSeparatorRuneByteWidth)
|
||||||
|
|
@ -747,7 +748,7 @@ proc getSymbol(L: var TLexer, tok: var TToken) =
|
||||||
h = h !& ord(c)
|
h = h !& ord(c)
|
||||||
inc(pos)
|
inc(pos)
|
||||||
of '_':
|
of '_':
|
||||||
if buf[pos+1] notin SymChars:
|
if buf[pos+1] notin SymChars or isMagicIdentSeparatorRune(buf, pos+1):
|
||||||
lexMessage(L, errInvalidToken, "_")
|
lexMessage(L, errInvalidToken, "_")
|
||||||
break
|
break
|
||||||
inc(pos)
|
inc(pos)
|
||||||
|
|
@ -1056,7 +1057,8 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
inc(L.bufpos)
|
inc(L.bufpos)
|
||||||
of '_':
|
of '_':
|
||||||
inc(L.bufpos)
|
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.tokType = tkSymbol
|
||||||
tok.ident = getIdent("_")
|
tok.ident = getIdent("_")
|
||||||
else:
|
else:
|
||||||
|
|
@ -1077,6 +1079,9 @@ proc rawGetTok*(L: var TLexer, tok: var TToken) =
|
||||||
tok.tokType = tkCharLit
|
tok.tokType = tkCharLit
|
||||||
of '0'..'9':
|
of '0'..'9':
|
||||||
getNumber(L, tok)
|
getNumber(L, tok)
|
||||||
|
let c = L.buf[L.bufpos]
|
||||||
|
if c in SymChars+{'_'}:
|
||||||
|
lexMessage(L, errInvalidToken, c & " (\\" & $(ord(c)) & ')')
|
||||||
else:
|
else:
|
||||||
if c in OpChars:
|
if c in OpChars:
|
||||||
getOperator(L, tok)
|
getOperator(L, tok)
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,11 @@ proc commandCheck =
|
||||||
rodPass()
|
rodPass()
|
||||||
compileProject()
|
compileProject()
|
||||||
|
|
||||||
proc commandDoc2 =
|
proc commandDoc2(json: bool) =
|
||||||
msgs.gErrorMax = high(int) # do not stop after first error
|
msgs.gErrorMax = high(int) # do not stop after first error
|
||||||
semanticPasses()
|
semanticPasses()
|
||||||
registerPass(docgen2Pass)
|
if json: registerPass(docgen2JsonPass)
|
||||||
|
else: registerPass(docgen2Pass)
|
||||||
#registerPass(cleanupPass())
|
#registerPass(cleanupPass())
|
||||||
compileProject()
|
compileProject()
|
||||||
finishDoc2Pass(gProjectName)
|
finishDoc2Pass(gProjectName)
|
||||||
|
|
@ -281,7 +282,7 @@ proc mainCommand* =
|
||||||
gCmd = cmdDoc
|
gCmd = cmdDoc
|
||||||
loadConfigs(DocConfig)
|
loadConfigs(DocConfig)
|
||||||
defineSymbol("nimdoc")
|
defineSymbol("nimdoc")
|
||||||
commandDoc2()
|
commandDoc2(false)
|
||||||
of "rst2html":
|
of "rst2html":
|
||||||
gCmd = cmdRst2html
|
gCmd = cmdRst2html
|
||||||
loadConfigs(DocConfig)
|
loadConfigs(DocConfig)
|
||||||
|
|
@ -296,7 +297,13 @@ proc mainCommand* =
|
||||||
loadConfigs(DocConfig)
|
loadConfigs(DocConfig)
|
||||||
wantMainModule()
|
wantMainModule()
|
||||||
defineSymbol("nimdoc")
|
defineSymbol("nimdoc")
|
||||||
commandJSON()
|
commandJson()
|
||||||
|
of "jsondoc2":
|
||||||
|
gCmd = cmdDoc
|
||||||
|
loadConfigs(DocConfig)
|
||||||
|
wantMainModule()
|
||||||
|
defineSymbol("nimdoc")
|
||||||
|
commandDoc2(true)
|
||||||
of "buildindex":
|
of "buildindex":
|
||||||
gCmd = cmdDoc
|
gCmd = cmdDoc
|
||||||
loadConfigs(DocConfig)
|
loadConfigs(DocConfig)
|
||||||
|
|
|
||||||
|
|
@ -105,12 +105,13 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile =
|
||||||
resetModule(fileIdx)
|
resetModule(fileIdx)
|
||||||
return Yes
|
return Yes
|
||||||
|
|
||||||
if gMemCacheData[fileIdx].needsRecompile != Maybe:
|
# cycle detection: We claim that a cycle does no harm.
|
||||||
return gMemCacheData[fileIdx].needsRecompile
|
if gMemCacheData[fileIdx].needsRecompile == Probing:
|
||||||
|
return No
|
||||||
|
#return gMemCacheData[fileIdx].needsRecompile
|
||||||
|
|
||||||
if optForceFullMake in gGlobalOptions or
|
if optForceFullMake in gGlobalOptions or hashChanged(fileIdx):
|
||||||
hashChanged(fileIdx):
|
markDirty()
|
||||||
markDirty
|
|
||||||
|
|
||||||
if gMemCacheData[fileIdx].deps != nil:
|
if gMemCacheData[fileIdx].deps != nil:
|
||||||
gMemCacheData[fileIdx].needsRecompile = Probing
|
gMemCacheData[fileIdx].needsRecompile = Probing
|
||||||
|
|
@ -118,7 +119,7 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile =
|
||||||
let d = checkDepMem(dep)
|
let d = checkDepMem(dep)
|
||||||
if d in {Yes, Recompiled}:
|
if d in {Yes, Recompiled}:
|
||||||
# echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d
|
# echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d
|
||||||
markDirty
|
markDirty()
|
||||||
|
|
||||||
gMemCacheData[fileIdx].needsRecompile = No
|
gMemCacheData[fileIdx].needsRecompile = No
|
||||||
return No
|
return No
|
||||||
|
|
|
||||||
|
|
@ -518,7 +518,6 @@ const
|
||||||
warnGcUnsafe,
|
warnGcUnsafe,
|
||||||
hintPath,
|
hintPath,
|
||||||
hintDependency,
|
hintDependency,
|
||||||
hintExecuting,
|
|
||||||
hintCodeBegin, hintCodeEnd,
|
hintCodeBegin, hintCodeEnd,
|
||||||
hintSource, hintStackTrace,
|
hintSource, hintStackTrace,
|
||||||
hintGCStats},
|
hintGCStats},
|
||||||
|
|
@ -530,7 +529,7 @@ const
|
||||||
|
|
||||||
var
|
var
|
||||||
ForeignPackageNotes*: TNoteKinds = {hintProcessing, warnUnknownMagic,
|
ForeignPackageNotes*: TNoteKinds = {hintProcessing, warnUnknownMagic,
|
||||||
hintQuitCalled}
|
hintQuitCalled, hintExecuting}
|
||||||
filenameToIndexTbl = initTable[string, int32]()
|
filenameToIndexTbl = initTable[string, int32]()
|
||||||
fileInfos*: seq[TFileInfo] = @[]
|
fileInfos*: seq[TFileInfo] = @[]
|
||||||
systemFileIdx*: int32
|
systemFileIdx*: int32
|
||||||
|
|
@ -621,6 +620,7 @@ var
|
||||||
gHintCounter*: int = 0
|
gHintCounter*: int = 0
|
||||||
gWarnCounter*: int = 0
|
gWarnCounter*: int = 0
|
||||||
gErrorMax*: int = 1 # stop after gErrorMax errors
|
gErrorMax*: int = 1 # stop after gErrorMax errors
|
||||||
|
gMainPackageNotes*: TNoteKinds = NotesVerbosity[1]
|
||||||
|
|
||||||
proc unknownLineInfo*(): TLineInfo =
|
proc unknownLineInfo*(): TLineInfo =
|
||||||
result.line = int16(-1)
|
result.line = int16(-1)
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,7 @@ const
|
||||||
var
|
var
|
||||||
gConfigVars* = newStringTable(modeStyleInsensitive)
|
gConfigVars* = newStringTable(modeStyleInsensitive)
|
||||||
gDllOverrides = newStringTable(modeCaseInsensitive)
|
gDllOverrides = newStringTable(modeCaseInsensitive)
|
||||||
|
gModuleOverrides* = newStringTable(modeStyleInsensitive)
|
||||||
gPrefixDir* = "" # Overrides the default prefix dir in getPrefixDir proc.
|
gPrefixDir* = "" # Overrides the default prefix dir in getPrefixDir proc.
|
||||||
libpath* = ""
|
libpath* = ""
|
||||||
gProjectName* = "" # holds a name like 'nim'
|
gProjectName* = "" # holds a name like 'nim'
|
||||||
|
|
@ -374,6 +375,13 @@ proc rawFindFile2(f: string): string =
|
||||||
it = PStrEntry(it.next)
|
it = PStrEntry(it.next)
|
||||||
result = ""
|
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.} =
|
proc findFile*(f: string): string {.procvar.} =
|
||||||
if f.isAbsolute:
|
if f.isAbsolute:
|
||||||
result = if f.existsFile: f else: ""
|
result = if f.existsFile: f else: ""
|
||||||
|
|
@ -385,6 +393,7 @@ proc findFile*(f: string): string {.procvar.} =
|
||||||
result = f.rawFindFile2
|
result = f.rawFindFile2
|
||||||
if result.len == 0:
|
if result.len == 0:
|
||||||
result = f.toLower.rawFindFile2
|
result = f.toLower.rawFindFile2
|
||||||
|
patchModule()
|
||||||
|
|
||||||
proc findModule*(modulename, currentModule: string): string =
|
proc findModule*(modulename, currentModule: string): string =
|
||||||
# returns path to module
|
# returns path to module
|
||||||
|
|
@ -403,6 +412,7 @@ proc findModule*(modulename, currentModule: string): string =
|
||||||
result = currentPath / m
|
result = currentPath / m
|
||||||
if not existsFile(result):
|
if not existsFile(result):
|
||||||
result = findFile(m)
|
result = findFile(m)
|
||||||
|
patchModule()
|
||||||
|
|
||||||
proc libCandidates*(s: string, dest: var seq[string]) =
|
proc libCandidates*(s: string, dest: var seq[string]) =
|
||||||
var le = strutils.find(s, '(')
|
var le = strutils.find(s, '(')
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
import
|
import
|
||||||
ast, modules, passes, passaux, condsyms,
|
ast, modules, passes, passaux, condsyms,
|
||||||
options, nimconf, lists, sem, semdata, llstream, vm, vmdef, commands, msgs,
|
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:
|
# we support 'cmpIgnoreStyle' natively for efficiency:
|
||||||
from strutils import cmpIgnoreStyle
|
from strutils import cmpIgnoreStyle
|
||||||
|
|
@ -122,6 +122,12 @@ proc setupVM*(module: PSym; scriptName: string): PEvalContext =
|
||||||
cbconf warningImpl:
|
cbconf warningImpl:
|
||||||
processSpecificNote(a.getString 0, wWarning, passPP, unknownLineInfo(),
|
processSpecificNote(a.getString 0, wWarning, passPP, unknownLineInfo(),
|
||||||
a.getString 1)
|
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) =
|
proc runNimScript*(scriptName: string; freshDefines=true) =
|
||||||
passes.gIncludeFile = includeModule
|
passes.gIncludeFile = includeModule
|
||||||
|
|
|
||||||
|
|
@ -1065,8 +1065,11 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
result.typ = makeTypeDesc(c, s.typ)
|
result.typ = makeTypeDesc(c, s.typ)
|
||||||
of skField:
|
of skField:
|
||||||
if c.p != nil and c.p.selfSym != nil:
|
var p = c.p
|
||||||
var ty = skipTypes(c.p.selfSym.typ, {tyGenericInst, tyVar, tyPtr, tyRef})
|
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})
|
while tfBorrowDot in ty.flags: ty = ty.skipTypes({tyDistinct})
|
||||||
var check: PNode = nil
|
var check: PNode = nil
|
||||||
if ty.kind == tyObject:
|
if ty.kind == tyObject:
|
||||||
|
|
@ -1079,7 +1082,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
markUsed(n.info, f)
|
markUsed(n.info, f)
|
||||||
styleCheckUse(n.info, f)
|
styleCheckUse(n.info, f)
|
||||||
result = newNodeIT(nkDotExpr, n.info, f.typ)
|
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
|
result.add newSymNode(f) # we now have the correct field
|
||||||
if check != nil:
|
if check != nil:
|
||||||
check.sons[0] = result
|
check.sons[0] = result
|
||||||
|
|
|
||||||
|
|
@ -411,6 +411,13 @@ proc semUsing(c: PContext; n: PNode): PNode =
|
||||||
if a.sons[length-1].kind != nkEmpty:
|
if a.sons[length-1].kind != nkEmpty:
|
||||||
localError(a.info, "'using' sections cannot contain assignments")
|
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 =
|
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
var b: PNode
|
var b: PNode
|
||||||
result = copyNode(n)
|
result = copyNode(n)
|
||||||
|
|
@ -445,8 +452,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
#changeType(def.skipConv, typ, check=true)
|
#changeType(def.skipConv, typ, check=true)
|
||||||
else:
|
else:
|
||||||
typ = skipIntLit(def.typ)
|
typ = skipIntLit(def.typ)
|
||||||
if typ.kind in {tySequence, tyArray, tySet} and
|
if hasEmpty(typ):
|
||||||
typ.lastSon.kind == tyEmpty:
|
|
||||||
localError(def.info, errCannotInferTypeOfTheLiteral,
|
localError(def.info, errCannotInferTypeOfTheLiteral,
|
||||||
($typ.kind).substr(2).toLower)
|
($typ.kind).substr(2).toLower)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1746,8 +1746,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||||
if formal.ast == nil:
|
if formal.ast == nil:
|
||||||
if formal.typ.kind == tyVarargs:
|
if formal.typ.kind == tyVarargs:
|
||||||
var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
|
var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
|
||||||
addSon(m.call, implicitConv(nkHiddenStdConv, formal.typ,
|
setSon(m.call, formal.position + 1,
|
||||||
container, m, c))
|
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
||||||
else:
|
else:
|
||||||
# no default value
|
# no default value
|
||||||
m.state = csNoMatch
|
m.state = csNoMatch
|
||||||
|
|
|
||||||
|
|
@ -541,7 +541,9 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||||
else:
|
else:
|
||||||
result.add typeToString(t.sons[0])
|
result.add typeToString(t.sons[0])
|
||||||
of tyRange:
|
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:
|
if prefer != preferExported:
|
||||||
result.add("(" & typeToString(t.sons[0]) & ")")
|
result.add("(" & typeToString(t.sons[0]) & ")")
|
||||||
of tyProc:
|
of tyProc:
|
||||||
|
|
@ -1315,6 +1317,9 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
result = computeSizeAux(typ.base, a)
|
result = computeSizeAux(typ.base, a)
|
||||||
of tyForward: return szIllegalRecursion
|
of tyForward: return szIllegalRecursion
|
||||||
|
of tyStatic:
|
||||||
|
if typ.n != nil: result = computeSizeAux(lastSon(typ), a)
|
||||||
|
else: result = szUnknownSize
|
||||||
else:
|
else:
|
||||||
#internalError("computeSizeAux()")
|
#internalError("computeSizeAux()")
|
||||||
result = szUnknownSize
|
result = szUnknownSize
|
||||||
|
|
|
||||||
|
|
@ -1686,10 +1686,10 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
of skType:
|
of skType:
|
||||||
genTypeLit(c, s.typ, dest)
|
genTypeLit(c, s.typ, dest)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
if c.prc.sym.kind == skMacro:
|
if c.prc.sym != nil and c.prc.sym.kind == skMacro:
|
||||||
genRdVar(c, n, dest, flags)
|
genRdVar(c, n, dest, flags)
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "cannot generate code for: " & s.name.s)
|
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
|
||||||
else:
|
else:
|
||||||
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
|
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
|
||||||
of nkCallKinds:
|
of nkCallKinds:
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,6 @@ arm.linux.gcc.linkerexe = "arm-linux-gcc"
|
||||||
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
|
mips.linux.gcc.exe = "mips-openwrt-linux-gcc"
|
||||||
mips.linux.gcc.linkerexe = "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/core"
|
||||||
path="$lib/deprecated/pure"
|
path="$lib/deprecated/pure"
|
||||||
path="$lib/pure/collections"
|
path="$lib/pure/collections"
|
||||||
|
|
@ -168,10 +164,5 @@ vcc.options.always = "/nologo"
|
||||||
vcc.options.speed = "/O2 /arch:SSE2"
|
vcc.options.speed = "/O2 /arch:SSE2"
|
||||||
vcc.options.size = "/O1"
|
vcc.options.size = "/O1"
|
||||||
|
|
||||||
# Configuration for the Digital Mars C/C++ compiler:
|
|
||||||
@if windows:
|
|
||||||
dmc.path = r"$nimrod\dist\dm\bin"
|
|
||||||
@end
|
|
||||||
|
|
||||||
# Configuration for the Tiny C Compiler:
|
# Configuration for the Tiny C Compiler:
|
||||||
tcc.options.always = "-w"
|
tcc.options.always = "-w"
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ Advanced commands:
|
||||||
//rst2html convert a reStructuredText file to HTML
|
//rst2html convert a reStructuredText file to HTML
|
||||||
//rst2tex convert a reStructuredText file to TeX
|
//rst2tex convert a reStructuredText file to TeX
|
||||||
//jsondoc extract the documentation to a json file
|
//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
|
//buildIndex build an index for the whole documentation
|
||||||
//run run the project (with Tiny C backend; buggy!)
|
//run run the project (with Tiny C backend; buggy!)
|
||||||
//genDepend generate a DOT file containing the
|
//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.data[q.wr] = item
|
||||||
q.wr = (q.wr + 1) and q.mask
|
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.} =
|
proc pop*[T](q: var Queue[T]): T {.inline, discardable.} =
|
||||||
## Remove and returns the first (oldest) element of the queue `q`.
|
## Remove and returns the first (oldest) element of the queue `q`.
|
||||||
emptyCheck(q)
|
emptyCheck(q)
|
||||||
dec q.count
|
dec q.count
|
||||||
result = q.data[q.rd]
|
result = q.data[q.rd]
|
||||||
|
q.data[q.rd] = default(type(result))
|
||||||
q.rd = (q.rd + 1) and q.mask
|
q.rd = (q.rd + 1) and q.mask
|
||||||
|
|
||||||
proc enqueue*[T](q: var Queue[T], item: T) =
|
proc enqueue*[T](q: var Queue[T], item: T) =
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,39 @@
|
||||||
## semantics, this means that ``=`` performs a copy of the hash table.
|
## semantics, this means that ``=`` performs a copy of the hash table.
|
||||||
## For **reference** semantics use the ``Ref`` variant: ``TableRef``,
|
## For **reference** semantics use the ``Ref`` variant: ``TableRef``,
|
||||||
## ``OrderedTableRef``, ``CountTableRef``.
|
## ``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
|
## 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
|
## 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)
|
discard getTok(p)
|
||||||
while p.tok != tkCurlyRi:
|
while p.tok != tkCurlyRi:
|
||||||
if p.tok != tkString:
|
if p.tok != tkString:
|
||||||
raiseParseErr(p, "string literal as key expected")
|
raiseParseErr(p, "string literal as key")
|
||||||
var key = p.a
|
var key = p.a
|
||||||
discard getTok(p)
|
discard getTok(p)
|
||||||
eat(p, tkColon)
|
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")
|
gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
|
||||||
# now it is buffered in the ZCT
|
# now it is buffered in the ZCT
|
||||||
res.typ = typ
|
res.typ = typ
|
||||||
when leakDetector and not hasThreadSupport:
|
when leakDetector:
|
||||||
if framePtr != nil and framePtr.prev != nil:
|
res.filename = nil
|
||||||
res.filename = framePtr.prev.filename
|
res.line = 0
|
||||||
res.line = framePtr.prev.line
|
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
|
# refcount is zero, color is black, but mark it to be in the ZCT
|
||||||
res.refcount = ZctFlag
|
res.refcount = ZctFlag
|
||||||
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
|
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")
|
sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
|
||||||
# now it is buffered in the ZCT
|
# now it is buffered in the ZCT
|
||||||
res.typ = typ
|
res.typ = typ
|
||||||
when leakDetector and not hasThreadSupport:
|
when leakDetector:
|
||||||
if framePtr != nil and framePtr.prev != nil:
|
res.filename = nil
|
||||||
res.filename = framePtr.prev.filename
|
res.line = 0
|
||||||
res.line = framePtr.prev.line
|
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
|
res.refcount = rcIncrement # refcount is 1
|
||||||
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
|
sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
|
||||||
when logGC: writeCell("new cell", res)
|
when logGC: writeCell("new cell", res)
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,21 @@ proc hint*(name: string; val: bool) =
|
||||||
let v = if val: "on" else: "off"
|
let v = if val: "on" else: "off"
|
||||||
hintImpl(name & "]:" & v, "hint[" & name & "]:" & v)
|
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 =
|
proc getCommand*(): string =
|
||||||
## Gets the Nim command that the compiler has been invoked with, for example
|
## Gets the Nim command that the compiler has been invoked with, for example
|
||||||
## "c", "js", "build", "help".
|
## "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 """
|
discard """
|
||||||
cmd: "nim default $file"
|
cmd: "nim default $file"
|
||||||
output: '''hello world!'''
|
output: '''hello world! 0.5'''
|
||||||
msg: '''[NimScript] exec: gcc -v'''
|
msg: '''[NimScript] exec: gcc -v'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
when not defined(definedefine):
|
when not defined(definedefine):
|
||||||
{.fatal: "wrong nim script configuration".}
|
{.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)
|
warning("uninit", off)
|
||||||
hint("processing", off)
|
hint("processing", off)
|
||||||
|
#--verbosity:2
|
||||||
|
patchFile("stdlib", "math", "mymath")
|
||||||
|
|
||||||
task listDirs, "lists every subdirectory":
|
task listDirs, "lists every subdirectory":
|
||||||
for x in listDirs("."):
|
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
|
- The ``-d/--define`` flag can now optionally take a value to be used
|
||||||
by code at compile time.
|
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
|
Language Additions
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue