merge devel
This commit is contained in:
commit
3e5c94664d
25 changed files with 408 additions and 243 deletions
|
|
@ -11,7 +11,7 @@
|
||||||
to deal with!
|
to deal with!
|
||||||
- Indexing into a ``cstring`` for the JS target is now mapped
|
- Indexing into a ``cstring`` for the JS target is now mapped
|
||||||
to ``charCodeAt``.
|
to ``charCodeAt``.
|
||||||
- Assignments that would "slice" an object into its supertype are not prevented
|
- Assignments that would "slice" an object into its supertype are now prevented
|
||||||
at runtime. Use ``ref object`` with inheritance rather than ``object`` with
|
at runtime. Use ``ref object`` with inheritance rather than ``object`` with
|
||||||
inheritance to prevent this issue.
|
inheritance to prevent this issue.
|
||||||
|
|
||||||
|
|
@ -81,7 +81,10 @@
|
||||||
Imported exceptions can be raised and caught just like Nim exceptions.
|
Imported exceptions can be raised and caught just like Nim exceptions.
|
||||||
More details in language manual.
|
More details in language manual.
|
||||||
|
|
||||||
- Range float typed, example `range[0.0 .. Inf]`. More details in language manual.
|
- ``nil`` for strings/seqs is finally gone. Instead the default value for
|
||||||
|
these is ``"" / @[]``.
|
||||||
|
|
||||||
|
- Range float types, example `range[0.0 .. Inf]`. More details in language manual.
|
||||||
|
|
||||||
### Tool changes
|
### Tool changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,15 +125,15 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
if skipTypes(n.typ, abstractInst).kind == tyVar and
|
if skipTypes(n.typ, abstractInst).kind == tyVar and
|
||||||
not compileToCpp(p.module):
|
not compileToCpp(p.module):
|
||||||
result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
|
result = "(*$1)->data, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p)]
|
||||||
else:
|
else:
|
||||||
result = "$1->data, $1->$2" % [a.rdLoc, lenField(p)]
|
result = "$1->data, ($1 ? $1->$2 : 0)" % [a.rdLoc, lenField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))]
|
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))]
|
||||||
of tyPtr, tyRef:
|
of tyPtr, tyRef:
|
||||||
case lastSon(a.t).kind
|
case lastSon(a.t).kind
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
result = "(*$1)->data, (*$1)->$2" % [a.rdLoc, lenField(p)]
|
result = "(*$1)->data, (*$1 ? (*$1)->$2 : 0)" % [a.rdLoc, lenField(p)]
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))]
|
result = "$1, $2" % [rdLoc(a), rope(lengthOrd(lastSon(a.t)))]
|
||||||
else:
|
else:
|
||||||
|
|
@ -143,7 +143,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
|
||||||
proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
|
proc genArgStringToCString(p: BProc, n: PNode): Rope {.inline.} =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
result = "$1->data" % [a.rdLoc]
|
result = "($1 ? $1->data : (NCSTRING)\"\")" % [a.rdLoc]
|
||||||
|
|
||||||
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
|
proc genArg(p: BProc, n: PNode, param: PSym; call: PNode): Rope =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
|
|
|
||||||
|
|
@ -882,7 +882,7 @@ proc genIndexCheck(p: BProc; arr, idx: TLoc) =
|
||||||
rdCharLoc(idx), first, intLiteral(lastOrd(ty)))
|
rdCharLoc(idx), first, intLiteral(lastOrd(ty)))
|
||||||
of tySequence, tyString:
|
of tySequence, tyString:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
rdLoc(idx), rdLoc(arr), lenField(p))
|
rdLoc(idx), rdLoc(arr), lenField(p))
|
||||||
else: discard
|
else: discard
|
||||||
|
|
||||||
|
|
@ -907,11 +907,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
if ty.kind == tyString:
|
if ty.kind == tyString:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ((NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
"if (!$2 || (NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
rdLoc(b), rdLoc(a), lenField(p))
|
||||||
else:
|
else:
|
||||||
linefmt(p, cpsStmts,
|
linefmt(p, cpsStmts,
|
||||||
"if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
rdLoc(b), rdLoc(a), lenField(p))
|
||||||
if d.k == locNone: d.storage = OnHeap
|
if d.k == locNone: d.storage = OnHeap
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
|
|
@ -980,10 +980,10 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
for it in n.sons:
|
for it in n.sons:
|
||||||
if it.skipConv.kind == nkNilLit:
|
if it.skipConv.kind == nkNilLit:
|
||||||
add(args, ", \"nil\"")
|
add(args, ", \"\"")
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, it, a)
|
initLocExpr(p, it, a)
|
||||||
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
addf(args, ", $1? ($1)->data:\"\"", [rdLoc(a)])
|
||||||
p.module.includeHeader("<base/log.h>")
|
p.module.includeHeader("<base/log.h>")
|
||||||
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1034,7 +1034,7 @@ proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 1].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
inc(L, len(e.sons[i + 1].strVal))
|
inc(L, len(e.sons[i + 1].strVal))
|
||||||
else:
|
else:
|
||||||
addf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
|
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
|
||||||
add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
|
add(appends, rfmt(p.module, "#appendString($1, $2);$n", tmp.r, rdLoc(a)))
|
||||||
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
|
linefmt(p, cpsStmts, "$1 = #rawNewString($2$3);$n", tmp.r, lens, rope(L))
|
||||||
add(p.s(cpsStmts), appends)
|
add(p.s(cpsStmts), appends)
|
||||||
|
|
@ -1073,7 +1073,7 @@ proc genStrAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
if e.sons[i + 2].kind in {nkStrLit..nkTripleStrLit}:
|
||||||
inc(L, len(e.sons[i + 2].strVal))
|
inc(L, len(e.sons[i + 2].strVal))
|
||||||
else:
|
else:
|
||||||
addf(lens, "$1->$2 + ", [rdLoc(a), lenField(p)])
|
addf(lens, "($1 ? $1->$2 : 0) + ", [rdLoc(a), lenField(p)])
|
||||||
add(appends, rfmt(p.module, "#appendString($1, $2);$n",
|
add(appends, rfmt(p.module, "#appendString($1, $2);$n",
|
||||||
rdLoc(dest), rdLoc(a)))
|
rdLoc(dest), rdLoc(a)))
|
||||||
linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
linefmt(p, cpsStmts, "$1 = #resizeString($1, $2$3);$n",
|
||||||
|
|
@ -1086,17 +1086,17 @@ proc genSeqElemAppend(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
# seq = (typeof seq) incrSeq(&seq->Sup, sizeof(x));
|
||||||
# seq->data[seq->len-1] = x;
|
# seq->data[seq->len-1] = x;
|
||||||
let seqAppendPattern = if not p.module.compileToCpp:
|
let seqAppendPattern = if not p.module.compileToCpp:
|
||||||
"$1 = ($2) #incrSeqV2(&($1)->Sup, sizeof($3));$n"
|
"$1 = ($2) #incrSeqV3(&($1)->Sup, $3);$n"
|
||||||
else:
|
else:
|
||||||
"$1 = ($2) #incrSeqV2($1, sizeof($3));$n"
|
"$1 = ($2) #incrSeqV3($1, $3);$n"
|
||||||
var a, b, dest, tmpL: TLoc
|
var a, b, dest, tmpL: TLoc
|
||||||
initLocExpr(p, e.sons[1], a)
|
initLocExpr(p, e.sons[1], a)
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
let bt = skipTypes(e.sons[2].typ, {tyVar})
|
let seqType = skipTypes(e.sons[1].typ, {tyVar})
|
||||||
lineCg(p, cpsStmts, seqAppendPattern, [
|
lineCg(p, cpsStmts, seqAppendPattern, [
|
||||||
rdLoc(a),
|
rdLoc(a),
|
||||||
getTypeDesc(p.module, e.sons[1].typ),
|
getTypeDesc(p.module, e.sons[1].typ),
|
||||||
getTypeDesc(p.module, bt)])
|
genTypeInfo(p.module, seqType, e.info)])
|
||||||
#if bt != b.t:
|
#if bt != b.t:
|
||||||
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
|
# echo "YES ", e.info, " new: ", typeToString(bt), " old: ", typeToString(b.t)
|
||||||
initLoc(dest, locExpr, e.sons[2], OnHeap)
|
initLoc(dest, locExpr, e.sons[2], OnHeap)
|
||||||
|
|
@ -1417,7 +1417,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
|
putIntoDest(p, b, e, "$1, $1Len_0" % [rdLoc(a)], a.storage)
|
||||||
of tyString, tySequence:
|
of tyString, tySequence:
|
||||||
putIntoDest(p, b, e,
|
putIntoDest(p, b, e,
|
||||||
"$1->data, $1->$2" % [rdLoc(a), lenField(p)], a.storage)
|
"$1->data, ($1 ? $1->$2 : 0)" % [rdLoc(a), lenField(p)], a.storage)
|
||||||
of tyArray:
|
of tyArray:
|
||||||
putIntoDest(p, b, e,
|
putIntoDest(p, b, e,
|
||||||
"$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.storage)
|
"$1, $2" % [rdLoc(a), rope(lengthOrd(a.t))], a.storage)
|
||||||
|
|
@ -1500,13 +1500,13 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
|
||||||
initLocExpr(p, e.sons[2], b)
|
initLocExpr(p, e.sons[2], b)
|
||||||
let t = skipTypes(e.sons[1].typ, {tyVar})
|
let t = skipTypes(e.sons[1].typ, {tyVar})
|
||||||
let setLenPattern = if not p.module.compileToCpp:
|
let setLenPattern = if not p.module.compileToCpp:
|
||||||
"$1 = ($3) #setLengthSeq(&($1)->Sup, sizeof($4), $2);$n"
|
"$1 = ($3) #setLengthSeqV2(&($1)->Sup, $4, $2);$n"
|
||||||
else:
|
else:
|
||||||
"$1 = ($3) #setLengthSeq($1, sizeof($4), $2);$n"
|
"$1 = ($3) #setLengthSeqV2($1, $4, $2);$n"
|
||||||
|
|
||||||
lineCg(p, cpsStmts, setLenPattern, [
|
lineCg(p, cpsStmts, setLenPattern, [
|
||||||
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
|
||||||
getTypeDesc(p.module, t.skipTypes(abstractInst).sons[0])])
|
genTypeInfo(p.module, t.skipTypes(abstractInst), e.info)])
|
||||||
gcUsage(e)
|
gcUsage(e)
|
||||||
|
|
||||||
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
|
proc genSetLengthStr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
|
|
@ -1740,7 +1740,7 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
||||||
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
initLocExpr(p, n.sons[0], a)
|
initLocExpr(p, n.sons[0], a)
|
||||||
putIntoDest(p, d, n, "$1->data" % [rdLoc(a)],
|
putIntoDest(p, d, n, "($1 ? $1->data : (NCSTRING)\"\")" % [rdLoc(a)],
|
||||||
a.storage)
|
a.storage)
|
||||||
|
|
||||||
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
||||||
|
|
@ -1755,16 +1755,14 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var x: TLoc
|
var x: TLoc
|
||||||
var a = e.sons[1]
|
var a = e.sons[1]
|
||||||
var b = e.sons[2]
|
var b = e.sons[2]
|
||||||
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
|
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
|
||||||
binaryExpr(p, e, d, "($1 == $2)")
|
|
||||||
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
|
|
||||||
initLocExpr(p, e.sons[2], x)
|
initLocExpr(p, e.sons[2], x)
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||||
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
|
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
|
||||||
initLocExpr(p, e.sons[1], x)
|
initLocExpr(p, e.sons[1], x)
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||||
else:
|
else:
|
||||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ proc countDefinedSymbols*(): int =
|
||||||
|
|
||||||
proc initDefines*() =
|
proc initDefines*() =
|
||||||
gSymbols = newStringTable(modeStyleInsensitive)
|
gSymbols = newStringTable(modeStyleInsensitive)
|
||||||
defineSymbol("nimrod") # 'nimrod' is always defined
|
|
||||||
# for bootstrapping purposes and old code:
|
# for bootstrapping purposes and old code:
|
||||||
defineSymbol("nimhygiene")
|
defineSymbol("nimhygiene")
|
||||||
defineSymbol("niminheritable")
|
defineSymbol("niminheritable")
|
||||||
|
|
@ -115,3 +114,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimHasNilChecks")
|
defineSymbol("nimHasNilChecks")
|
||||||
defineSymbol("nimSymKind")
|
defineSymbol("nimSymKind")
|
||||||
defineSymbol("nimVmEqIdent")
|
defineSymbol("nimVmEqIdent")
|
||||||
|
defineSymbol("nimNoNil")
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ proc mainCommand =
|
||||||
compileProject(newModuleGraph(), newIdentCache())
|
compileProject(newModuleGraph(), newIdentCache())
|
||||||
pretty.overwriteFiles()
|
pretty.overwriteFiles()
|
||||||
|
|
||||||
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
proc processCmdLine*(pass: TCmdLinePass, cmd: string, config: ConfigRef) =
|
||||||
var p = parseopt.initOptParser(cmd)
|
var p = parseopt.initOptParser(cmd)
|
||||||
var argsCount = 0
|
var argsCount = 0
|
||||||
gOnlyMainfile = true
|
gOnlyMainfile = true
|
||||||
|
|
@ -76,16 +76,16 @@ proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||||
of "wholeproject": gOnlyMainfile = false
|
of "wholeproject": gOnlyMainfile = false
|
||||||
of "besteffort": msgs.gErrorMax = high(int) # don't stop after first error
|
of "besteffort": msgs.gErrorMax = high(int) # don't stop after first error
|
||||||
else:
|
else:
|
||||||
processSwitch(pass, p)
|
processSwitch(pass, p, config)
|
||||||
of cmdArgument:
|
of cmdArgument:
|
||||||
options.gProjectName = unixToNativePath(p.key)
|
options.gProjectName = unixToNativePath(p.key)
|
||||||
# if processArgument(pass, p, argsCount): break
|
# if processArgument(pass, p, argsCount): break
|
||||||
|
|
||||||
proc handleCmdLine() =
|
proc handleCmdLine(config: ConfigRef) =
|
||||||
if paramCount() == 0:
|
if paramCount() == 0:
|
||||||
stdout.writeLine(Usage)
|
stdout.writeLine(Usage)
|
||||||
else:
|
else:
|
||||||
processCmdLine(passCmd1, "")
|
processCmdLine(passCmd1, "", config)
|
||||||
if gProjectName != "":
|
if gProjectName != "":
|
||||||
try:
|
try:
|
||||||
gProjectFull = canonicalizePath(gProjectName)
|
gProjectFull = canonicalizePath(gProjectName)
|
||||||
|
|
@ -96,11 +96,11 @@ proc handleCmdLine() =
|
||||||
gProjectName = p.name
|
gProjectName = p.name
|
||||||
else:
|
else:
|
||||||
gProjectPath = getCurrentDir()
|
gProjectPath = getCurrentDir()
|
||||||
loadConfigs(DefaultConfig) # load all config files
|
loadConfigs(DefaultConfig, config) # load all config files
|
||||||
# now process command line arguments again, because some options in the
|
# now process command line arguments again, because some options in the
|
||||||
# command line can overwite the config file's settings
|
# command line can overwite the config file's settings
|
||||||
extccomp.initVars()
|
extccomp.initVars()
|
||||||
processCmdLine(passCmd2, "")
|
processCmdLine(passCmd2, "", config)
|
||||||
mainCommand()
|
mainCommand()
|
||||||
|
|
||||||
when compileOption("gc", "v2") or compileOption("gc", "refc"):
|
when compileOption("gc", "v2") or compileOption("gc", "refc"):
|
||||||
|
|
@ -108,4 +108,4 @@ when compileOption("gc", "v2") or compileOption("gc", "refc"):
|
||||||
|
|
||||||
condsyms.initDefines()
|
condsyms.initDefines()
|
||||||
defineSymbol "nimfix"
|
defineSymbol "nimfix"
|
||||||
handleCmdline()
|
handleCmdline newConfigRef()
|
||||||
|
|
|
||||||
|
|
@ -153,8 +153,9 @@ proc commonType*(x, y: PType): PType =
|
||||||
if a.kind in {tyRef, tyPtr}:
|
if a.kind in {tyRef, tyPtr}:
|
||||||
k = a.kind
|
k = a.kind
|
||||||
if b.kind != a.kind: return x
|
if b.kind != a.kind: return x
|
||||||
a = a.lastSon
|
# bug #7601, array construction of ptr generic
|
||||||
b = b.lastSon
|
a = a.lastSon.skipTypes({tyGenericInst})
|
||||||
|
b = b.lastSon.skipTypes({tyGenericInst})
|
||||||
if a.kind == tyObject and b.kind == tyObject:
|
if a.kind == tyObject and b.kind == tyObject:
|
||||||
result = commonSuperclass(a, b)
|
result = commonSuperclass(a, b)
|
||||||
# this will trigger an error later:
|
# this will trigger an error later:
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
filter: TSymKinds,
|
filter: TSymKinds,
|
||||||
best, alt: var TCandidate,
|
best, alt: var TCandidate,
|
||||||
errors: var CandidateErrors,
|
errors: var CandidateErrors,
|
||||||
diagnosticsFlag = false) =
|
diagnosticsFlag: bool,
|
||||||
|
errorsEnabled: bool) =
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
var sym = initOverloadIter(o, c, headSymbol)
|
var sym = initOverloadIter(o, c, headSymbol)
|
||||||
var scope = o.lastOverloadScope
|
var scope = o.lastOverloadScope
|
||||||
|
|
@ -68,6 +69,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
||||||
let counterInitial = c.currentScope.symbols.counter
|
let counterInitial = c.currentScope.symbols.counter
|
||||||
var syms: seq[tuple[s: PSym, scope: int]]
|
var syms: seq[tuple[s: PSym, scope: int]]
|
||||||
|
var noSyms = true
|
||||||
var nextSymIndex = 0
|
var nextSymIndex = 0
|
||||||
while sym != nil:
|
while sym != nil:
|
||||||
if sym.kind in filter:
|
if sym.kind in filter:
|
||||||
|
|
@ -102,7 +104,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
var cmp = cmpCandidates(best, z)
|
var cmp = cmpCandidates(best, z)
|
||||||
if cmp < 0: best = z # x is better than the best so far
|
if cmp < 0: best = z # x is better than the best so far
|
||||||
elif cmp == 0: alt = z # x is as good as the best so far
|
elif cmp == 0: alt = z # x is as good as the best so far
|
||||||
elif errors != nil or z.diagnostics != nil:
|
elif errorsEnabled or z.diagnosticsEnabled:
|
||||||
errors.safeAdd(CandidateError(
|
errors.safeAdd(CandidateError(
|
||||||
sym: sym,
|
sym: sym,
|
||||||
unmatchedVarParam: int z.mutabilityProblem,
|
unmatchedVarParam: int z.mutabilityProblem,
|
||||||
|
|
@ -113,7 +115,8 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
# before any further candidate init and compare. SLOW, but rare case.
|
# before any further candidate init and compare. SLOW, but rare case.
|
||||||
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
||||||
best, alt, o, diagnosticsFlag)
|
best, alt, o, diagnosticsFlag)
|
||||||
if syms == nil:
|
noSyms = false
|
||||||
|
if noSyms:
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
scope = o.lastOverloadScope
|
scope = o.lastOverloadScope
|
||||||
elif nextSymIndex < syms.len:
|
elif nextSymIndex < syms.len:
|
||||||
|
|
@ -206,7 +209,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
if errorOutputs == {}:
|
if errorOutputs == {}:
|
||||||
# fail fast:
|
# fail fast:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
if errors.isNil or errors.len == 0:
|
if errors.len == 0:
|
||||||
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -227,7 +230,8 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
|
||||||
if symx.kind in routineKinds:
|
if symx.kind in routineKinds:
|
||||||
errors.add(CandidateError(sym: symx,
|
errors.add(CandidateError(sym: symx,
|
||||||
unmatchedVarParam: 0, firstMismatch: 0,
|
unmatchedVarParam: 0, firstMismatch: 0,
|
||||||
diagnostics: nil))
|
diagnostics: nil,
|
||||||
|
enabled: false))
|
||||||
symx = nextOverloadIter(o, c, headSymbol)
|
symx = nextOverloadIter(o, c, headSymbol)
|
||||||
if errors.len == 0:
|
if errors.len == 0:
|
||||||
localError(n.info, "could not resolve: " & $n)
|
localError(n.info, "could not resolve: " & $n)
|
||||||
|
|
@ -236,7 +240,8 @@ proc bracketNotFoundError(c: PContext; n: PNode) =
|
||||||
|
|
||||||
proc resolveOverloads(c: PContext, n, orig: PNode,
|
proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
filter: TSymKinds, flags: TExprFlags,
|
filter: TSymKinds, flags: TExprFlags,
|
||||||
errors: var CandidateErrors): TCandidate =
|
errors: var CandidateErrors,
|
||||||
|
errorsEnabled: bool): TCandidate =
|
||||||
var initialBinding: PNode
|
var initialBinding: PNode
|
||||||
var alt: TCandidate
|
var alt: TCandidate
|
||||||
var f = n.sons[0]
|
var f = n.sons[0]
|
||||||
|
|
@ -249,7 +254,8 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
|
|
||||||
template pickBest(headSymbol) =
|
template pickBest(headSymbol) =
|
||||||
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
|
pickBestCandidate(c, headSymbol, n, orig, initialBinding,
|
||||||
filter, result, alt, errors, efExplain in flags)
|
filter, result, alt, errors, efExplain in flags,
|
||||||
|
errorsEnabled)
|
||||||
pickBest(f)
|
pickBest(f)
|
||||||
|
|
||||||
let overloadsState = result.state
|
let overloadsState = result.state
|
||||||
|
|
@ -423,9 +429,8 @@ proc tryDeref(n: PNode): PNode =
|
||||||
|
|
||||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds, flags: TExprFlags): PNode =
|
filter: TSymKinds, flags: TExprFlags): PNode =
|
||||||
var errors: CandidateErrors = if efExplain in flags: @[]
|
var errors: CandidateErrors = if efExplain in flags: @[] else: nil
|
||||||
else: nil
|
var r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
|
||||||
var r = resolveOverloads(c, n, nOrig, filter, flags, errors)
|
|
||||||
if r.state == csMatch:
|
if r.state == csMatch:
|
||||||
# this may be triggered, when the explain pragma is used
|
# this may be triggered, when the explain pragma is used
|
||||||
if errors.len > 0:
|
if errors.len > 0:
|
||||||
|
|
@ -443,7 +448,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
# into sigmatch with hidden conversion produced there
|
# into sigmatch with hidden conversion produced there
|
||||||
#
|
#
|
||||||
n.sons[1] = n.sons[1].tryDeref
|
n.sons[1] = n.sons[1].tryDeref
|
||||||
var r = resolveOverloads(c, n, nOrig, filter, flags, errors)
|
var r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
|
||||||
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
if r.state == csMatch: result = semResolvedCall(c, n, r)
|
||||||
else:
|
else:
|
||||||
# get rid of the deref again for a better error message:
|
# get rid of the deref again for a better error message:
|
||||||
|
|
|
||||||
|
|
@ -63,7 +63,7 @@ type
|
||||||
# to the user.
|
# to the user.
|
||||||
efWantStmt, efAllowStmt, efDetermineType, efExplain,
|
efWantStmt, efAllowStmt, efDetermineType, efExplain,
|
||||||
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
|
||||||
efNoProcvarCheck, efNoEvaluateGeneric, efInCall, efFromHlo,
|
efNoEvaluateGeneric, efInCall, efFromHlo
|
||||||
|
|
||||||
TExprFlags* = set[TExprFlag]
|
TExprFlags* = set[TExprFlag]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
else:
|
else:
|
||||||
if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
|
|
||||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||||
|
|
||||||
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
|
|
@ -63,8 +62,6 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||||
localError(n.info, errExprXHasNoType,
|
localError(n.info, errExprXHasNoType,
|
||||||
renderTree(result, {renderNoComments}))
|
renderTree(result, {renderNoComments}))
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
else:
|
|
||||||
semProcvarCheck(c, result)
|
|
||||||
|
|
||||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
result = symChoice(c, n, s, scClosed)
|
result = symChoice(c, n, s, scClosed)
|
||||||
|
|
@ -308,7 +305,9 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
maybeLiftType(t2, c, n.info)
|
maybeLiftType(t2, c, n.info)
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(c, m, t2)
|
initCandidate(c, m, t2)
|
||||||
if efExplain in flags: m.diagnostics = @[]
|
if efExplain in flags:
|
||||||
|
m.diagnostics = @[]
|
||||||
|
m.diagnosticsEnabled = true
|
||||||
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
result = newIntNode(nkIntLit, ord(match))
|
||||||
|
|
||||||
|
|
@ -540,7 +539,6 @@ proc analyseIfAddressTakenInCall(c: PContext, n: PNode) =
|
||||||
# we need to recurse explicitly here as converters can create nested
|
# we need to recurse explicitly here as converters can create nested
|
||||||
# calls and then they wouldn't be analysed otherwise
|
# calls and then they wouldn't be analysed otherwise
|
||||||
analyseIfAddressTakenInCall(c, n.sons[i])
|
analyseIfAddressTakenInCall(c, n.sons[i])
|
||||||
semProcvarCheck(c, n.sons[i])
|
|
||||||
if i < sonsLen(t) and
|
if i < sonsLen(t) and
|
||||||
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
skipTypes(t.sons[i], abstractInst-{tyTypeDesc}).kind == tyVar:
|
||||||
if n.sons[i].kind != nkHiddenAddr:
|
if n.sons[i].kind != nkHiddenAddr:
|
||||||
|
|
@ -1245,7 +1243,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
# make sure we don't evaluate generic macros/templates
|
# make sure we don't evaluate generic macros/templates
|
||||||
n.sons[0] = semExprWithType(c, n.sons[0],
|
n.sons[0] = semExprWithType(c, n.sons[0],
|
||||||
{efNoProcvarCheck, efNoEvaluateGeneric})
|
{efNoEvaluateGeneric})
|
||||||
let arr = skipTypes(n.sons[0].typ, {tyGenericInst,
|
let arr = skipTypes(n.sons[0].typ, {tyGenericInst,
|
||||||
tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink})
|
tyVar, tyLent, tyPtr, tyRef, tyAlias, tySink})
|
||||||
case arr.kind
|
case arr.kind
|
||||||
|
|
|
||||||
|
|
@ -71,37 +71,12 @@ proc toCover(t: PType): BiggestInt =
|
||||||
else:
|
else:
|
||||||
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
|
result = lengthOrd(skipTypes(t, abstractVar-{tyTypeDesc}))
|
||||||
|
|
||||||
when false:
|
|
||||||
proc performProcvarCheck(c: PContext, info: TLineInfo, s: PSym) =
|
|
||||||
## Checks that the given symbol is a proper procedure variable, meaning
|
|
||||||
## that it
|
|
||||||
var smoduleId = getModule(s).id
|
|
||||||
if sfProcvar notin s.flags and s.typ.callConv == ccDefault and
|
|
||||||
smoduleId != c.module.id:
|
|
||||||
block outer:
|
|
||||||
for module in c.friendModules:
|
|
||||||
if smoduleId == module.id:
|
|
||||||
break outer
|
|
||||||
localError(info, errXCannotBePassedToProcVar, s.name.s)
|
|
||||||
|
|
||||||
template semProcvarCheck(c: PContext, n: PNode) =
|
|
||||||
when false:
|
|
||||||
var n = n.skipConv
|
|
||||||
if n.kind in nkSymChoices:
|
|
||||||
for x in n:
|
|
||||||
if x.sym.kind in {skProc, skMethod, skConverter, skIterator}:
|
|
||||||
performProcvarCheck(c, n.info, x.sym)
|
|
||||||
elif n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter,
|
|
||||||
skIterator}:
|
|
||||||
performProcvarCheck(c, n.info, n.sym)
|
|
||||||
|
|
||||||
proc semProc(c: PContext, n: PNode): PNode
|
proc semProc(c: PContext, n: PNode): PNode
|
||||||
|
|
||||||
proc semExprBranch(c: PContext, n: PNode): PNode =
|
proc semExprBranch(c: PContext, n: PNode): PNode =
|
||||||
result = semExpr(c, n)
|
result = semExpr(c, n)
|
||||||
if result.typ != nil:
|
if result.typ != nil:
|
||||||
# XXX tyGenericInst here?
|
# XXX tyGenericInst here?
|
||||||
semProcvarCheck(c, result)
|
|
||||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||||
|
|
||||||
proc semExprBranchScope(c: PContext, n: PNode): PNode =
|
proc semExprBranchScope(c: PContext, n: PNode): PNode =
|
||||||
|
|
@ -384,7 +359,7 @@ proc checkNilable(v: PSym) =
|
||||||
|
|
||||||
include semasgn
|
include semasgn
|
||||||
|
|
||||||
proc addToVarSection(c: PContext; result: var PNode; orig, identDefs: PNode) =
|
proc addToVarSection(c: PContext; result: PNode; orig, identDefs: PNode) =
|
||||||
let L = identDefs.len
|
let L = identDefs.len
|
||||||
let value = identDefs[L-1]
|
let value = identDefs[L-1]
|
||||||
if result.kind == nkStmtList:
|
if result.kind == nkStmtList:
|
||||||
|
|
@ -525,7 +500,6 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
localError(a.info, errXExpected, "tuple")
|
localError(a.info, errXExpected, "tuple")
|
||||||
elif length-2 != sonsLen(tup):
|
elif length-2 != sonsLen(tup):
|
||||||
localError(a.info, errWrongNumberOfVariables)
|
localError(a.info, errWrongNumberOfVariables)
|
||||||
else:
|
|
||||||
b = newNodeI(nkVarTuple, a.info)
|
b = newNodeI(nkVarTuple, a.info)
|
||||||
newSons(b, length)
|
newSons(b, length)
|
||||||
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
|
b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
|
||||||
|
|
@ -572,7 +546,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||||
addToVarSection(c, result, n, b)
|
addToVarSection(c, result, n, b)
|
||||||
else:
|
else:
|
||||||
if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
|
if def.kind in {nkPar, nkTupleConstr}: v.ast = def[j]
|
||||||
setVarType(v, tup.sons[j])
|
# bug #7663, for 'nim check' this can be a non-tuple:
|
||||||
|
if tup.kind == tyTuple: setVarType(v, tup.sons[j])
|
||||||
|
else: v.typ = tup
|
||||||
b.sons[j] = newSymNode(v)
|
b.sons[j] = newSymNode(v)
|
||||||
checkNilable(v)
|
checkNilable(v)
|
||||||
if sfCompileTime in v.flags: hasCompileTime = true
|
if sfCompileTime in v.flags: hasCompileTime = true
|
||||||
|
|
@ -1588,9 +1564,11 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||||
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
|
||||||
if s.name.s[0] in {'.', '('}:
|
if s.name.s[0] in {'.', '('}:
|
||||||
if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
|
if s.name.s in [".", ".()", ".="] and {destructor, dotOperators} * c.features == {}:
|
||||||
message(n.info, warnDeprecated, "overloaded '.' and '()' operators are now .experimental; " & s.name.s)
|
localError(n.info, "the overloaded " & s.name.s &
|
||||||
|
" operator has to be enabled with {.experimental: \"dotOperators\".}")
|
||||||
elif s.name.s == "()" and callOperator notin c.features:
|
elif s.name.s == "()" and callOperator notin c.features:
|
||||||
message(n.info, warnDeprecated, "overloaded '()' operators are now .experimental; " & s.name.s)
|
localError(n.info, "the overloaded " & s.name.s &
|
||||||
|
" operator has to be enabled with {.experimental: \"callOperator\".}")
|
||||||
|
|
||||||
if n.sons[bodyPos].kind != nkEmpty:
|
if n.sons[bodyPos].kind != nkEmpty:
|
||||||
# for DLL generation it is annoying to check for sfImportc!
|
# for DLL generation it is annoying to check for sfImportc!
|
||||||
|
|
@ -1682,11 +1660,6 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||||
incl(s.typ.flags, tfCapturesEnv)
|
incl(s.typ.flags, tfCapturesEnv)
|
||||||
else:
|
else:
|
||||||
s.typ.callConv = ccInline
|
s.typ.callConv = ccInline
|
||||||
when false:
|
|
||||||
if s.typ.callConv != ccInline:
|
|
||||||
s.typ.callConv = ccClosure
|
|
||||||
# and they always at least use the 'env' for the state field:
|
|
||||||
incl(s.typ.flags, tfCapturesEnv)
|
|
||||||
if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
|
if n.sons[bodyPos].kind == nkEmpty and s.magic == mNone:
|
||||||
localError(n.info, errImplOfXexpected, s.name.s)
|
localError(n.info, errImplOfXexpected, s.name.s)
|
||||||
|
|
||||||
|
|
@ -1792,14 +1765,6 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
|
||||||
evalStaticStmt(c.module, c.cache, a, c.p.owner)
|
evalStaticStmt(c.module, c.cache, a, c.p.owner)
|
||||||
result = newNodeI(nkDiscardStmt, n.info, 1)
|
result = newNodeI(nkDiscardStmt, n.info, 1)
|
||||||
result.sons[0] = emptyNode
|
result.sons[0] = emptyNode
|
||||||
when false:
|
|
||||||
result = evalStaticStmt(c.module, a, c.p.owner)
|
|
||||||
if result.isNil:
|
|
||||||
LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
|
||||||
result = emptyNode
|
|
||||||
elif result.kind == nkEmpty:
|
|
||||||
result = newNodeI(nkDiscardStmt, n.info, 1)
|
|
||||||
result.sons[0] = emptyNode
|
|
||||||
|
|
||||||
proc usesResult(n: PNode): bool =
|
proc usesResult(n: PNode): bool =
|
||||||
# nkStmtList(expr) properly propagates the void context,
|
# nkStmtList(expr) properly propagates the void context,
|
||||||
|
|
@ -1841,40 +1806,6 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# nkNilLit, nkEmpty}:
|
# nkNilLit, nkEmpty}:
|
||||||
# dec last
|
# dec last
|
||||||
for i in countup(0, length - 1):
|
for i in countup(0, length - 1):
|
||||||
let k = n.sons[i].kind
|
|
||||||
case k
|
|
||||||
of nkFinally, nkExceptBranch:
|
|
||||||
# stand-alone finally and except blocks are
|
|
||||||
# transformed into regular try blocks:
|
|
||||||
#
|
|
||||||
# var f = fopen("somefile") | var f = fopen("somefile")
|
|
||||||
# finally: fclose(f) | try:
|
|
||||||
# ... | ...
|
|
||||||
# | finally:
|
|
||||||
# | fclose(f)
|
|
||||||
var deferPart: PNode
|
|
||||||
if k == nkDefer:
|
|
||||||
deferPart = newNodeI(nkFinally, n.sons[i].info)
|
|
||||||
deferPart.add n.sons[i].sons[0]
|
|
||||||
elif k == nkFinally:
|
|
||||||
message(n.info, warnDeprecated,
|
|
||||||
"use 'defer'; standalone 'finally'")
|
|
||||||
deferPart = n.sons[i]
|
|
||||||
else:
|
|
||||||
message(n.info, warnDeprecated,
|
|
||||||
"use an explicit 'try'; standalone 'except'")
|
|
||||||
deferPart = n.sons[i]
|
|
||||||
var tryStmt = newNodeI(nkTryStmt, n.sons[i].info)
|
|
||||||
var body = newNodeI(nkStmtList, n.sons[i].info)
|
|
||||||
if i < n.sonsLen - 1:
|
|
||||||
body.sons = n.sons[(i+1)..n.len-1]
|
|
||||||
tryStmt.addSon(body)
|
|
||||||
tryStmt.addSon(deferPart)
|
|
||||||
n.sons[i] = semTry(c, tryStmt)
|
|
||||||
n.sons.setLen(i+1)
|
|
||||||
n.typ = n.sons[i].typ
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
var expr = semExpr(c, n.sons[i], flags)
|
var expr = semExpr(c, n.sons[i], flags)
|
||||||
n.sons[i] = expr
|
n.sons[i] = expr
|
||||||
if c.matchedConcept != nil and expr.typ != nil and
|
if c.matchedConcept != nil and expr.typ != nil and
|
||||||
|
|
@ -1908,7 +1839,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
n.typ = n.sons[i].typ
|
n.typ = n.sons[i].typ
|
||||||
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
|
if not isEmptyType(n.typ): n.kind = nkStmtListExpr
|
||||||
if n.sons[i].kind in LastBlockStmts or
|
if n.sons[i].kind in LastBlockStmts or
|
||||||
n.sons[i].kind in nkCallKinds and n.sons[i][0].kind == nkSym and sfNoReturn in n.sons[i][0].sym.flags:
|
n.sons[i].kind in nkCallKinds and n.sons[i][0].kind == nkSym and
|
||||||
|
sfNoReturn in n.sons[i][0].sym.flags:
|
||||||
for j in countup(i + 1, length - 1):
|
for j in countup(i + 1, length - 1):
|
||||||
case n.sons[j].kind
|
case n.sons[j].kind
|
||||||
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
|
of nkPragma, nkCommentStmt, nkNilLit, nkEmpty, nkBlockExpr,
|
||||||
|
|
@ -1930,15 +1862,6 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
not (result.comment[0] == '#' and result.comment[1] == '#'):
|
not (result.comment[0] == '#' and result.comment[1] == '#'):
|
||||||
# it is an old-style comment statement: we replace it with 'discard ""':
|
# it is an old-style comment statement: we replace it with 'discard ""':
|
||||||
prettybase.replaceComment(result.info)
|
prettybase.replaceComment(result.info)
|
||||||
when false:
|
|
||||||
# a statement list (s; e) has the type 'e':
|
|
||||||
if result.kind == nkStmtList and result.len > 0:
|
|
||||||
var lastStmt = lastSon(result)
|
|
||||||
if lastStmt.kind != nkNilLit and not implicitlyDiscardable(lastStmt):
|
|
||||||
result.typ = lastStmt.typ
|
|
||||||
#localError(lastStmt.info, errGenerated,
|
|
||||||
# "Last expression must be explicitly returned if it " &
|
|
||||||
# "is discardable or discarded")
|
|
||||||
|
|
||||||
proc semStmt(c: PContext, n: PNode): PNode =
|
proc semStmt(c: PContext, n: PNode): PNode =
|
||||||
# now: simply an alias:
|
# now: simply an alias:
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ type
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
unmatchedVarParam*, firstMismatch*: int
|
unmatchedVarParam*, firstMismatch*: int
|
||||||
diagnostics*: seq[string]
|
diagnostics*: seq[string]
|
||||||
|
enabled*: bool
|
||||||
|
|
||||||
CandidateErrors* = seq[CandidateError]
|
CandidateErrors* = seq[CandidateError]
|
||||||
|
|
||||||
|
|
@ -60,7 +61,8 @@ type
|
||||||
# matching. they will be reset if the matching
|
# matching. they will be reset if the matching
|
||||||
# is not successful. may replace the bindings
|
# is not successful. may replace the bindings
|
||||||
# table in the future.
|
# table in the future.
|
||||||
diagnostics*: seq[string] # when this is not nil, the matching process
|
diagnostics*: seq[string] # \
|
||||||
|
# when diagnosticsEnabled, the matching process
|
||||||
# will collect extra diagnostics that will be
|
# will collect extra diagnostics that will be
|
||||||
# displayed to the user.
|
# displayed to the user.
|
||||||
# triggered when overload resolution fails
|
# triggered when overload resolution fails
|
||||||
|
|
@ -70,6 +72,7 @@ type
|
||||||
inheritancePenalty: int # to prefer closest father object type
|
inheritancePenalty: int # to prefer closest father object type
|
||||||
firstMismatch*: int # position of the first type mismatch for
|
firstMismatch*: int # position of the first type mismatch for
|
||||||
# better error messages
|
# better error messages
|
||||||
|
diagnosticsEnabled*: bool
|
||||||
|
|
||||||
TTypeRelFlag* = enum
|
TTypeRelFlag* = enum
|
||||||
trDontBind
|
trDontBind
|
||||||
|
|
@ -124,7 +127,8 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
|
||||||
idTablePut(c.bindings, key, val.skipIntLit)
|
idTablePut(c.bindings, key, val.skipIntLit)
|
||||||
|
|
||||||
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||||
binding: PNode, calleeScope = -1, diagnostics = false) =
|
binding: PNode, calleeScope = -1,
|
||||||
|
diagnosticsEnabled = false) =
|
||||||
initCandidateAux(ctx, c, callee.typ)
|
initCandidateAux(ctx, c, callee.typ)
|
||||||
c.calleeSym = callee
|
c.calleeSym = callee
|
||||||
if callee.kind in skProcKinds and calleeScope == -1:
|
if callee.kind in skProcKinds and calleeScope == -1:
|
||||||
|
|
@ -139,7 +143,8 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||||
c.calleeScope = 1
|
c.calleeScope = 1
|
||||||
else:
|
else:
|
||||||
c.calleeScope = calleeScope
|
c.calleeScope = calleeScope
|
||||||
c.diagnostics = if diagnostics: @[] else: nil
|
c.diagnostics = if diagnosticsEnabled: @[] else: nil
|
||||||
|
c.diagnosticsEnabled = diagnosticsEnabled
|
||||||
c.magic = c.calleeSym.magic
|
c.magic = c.calleeSym.magic
|
||||||
initIdTable(c.bindings)
|
initIdTable(c.bindings)
|
||||||
if binding != nil and callee.kind in routineKinds:
|
if binding != nil and callee.kind in routineKinds:
|
||||||
|
|
@ -724,7 +729,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||||
diagnostics: seq[string]
|
diagnostics: seq[string]
|
||||||
errorPrefix: string
|
errorPrefix: string
|
||||||
flags: TExprFlags = {}
|
flags: TExprFlags = {}
|
||||||
collectDiagnostics = m.diagnostics != nil or
|
collectDiagnostics = m.diagnosticsEnabled or
|
||||||
sfExplain in typeClass.sym.flags
|
sfExplain in typeClass.sym.flags
|
||||||
|
|
||||||
if collectDiagnostics:
|
if collectDiagnostics:
|
||||||
|
|
@ -743,7 +748,9 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||||
|
|
||||||
if collectDiagnostics:
|
if collectDiagnostics:
|
||||||
writelnHook = oldWriteHook
|
writelnHook = oldWriteHook
|
||||||
for msg in diagnostics: m.diagnostics.safeAdd msg
|
for msg in diagnostics:
|
||||||
|
m.diagnostics.safeAdd msg
|
||||||
|
m.diagnosticsEnabled = true
|
||||||
|
|
||||||
if checkedBody == nil: return nil
|
if checkedBody == nil: return nil
|
||||||
|
|
||||||
|
|
@ -1395,7 +1402,12 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
|
||||||
|
|
||||||
var aAsObject = roota.lastSon
|
var aAsObject = roota.lastSon
|
||||||
|
|
||||||
if fKind in {tyRef, tyPtr} and aAsObject.kind == fKind:
|
if fKind in {tyRef, tyPtr}:
|
||||||
|
if aAsObject.kind == tyObject:
|
||||||
|
# bug #7600, tyObject cannot be passed
|
||||||
|
# as argument to tyRef/tyPtr
|
||||||
|
return isNone
|
||||||
|
elif aAsObject.kind == fKind:
|
||||||
aAsObject = aAsObject.base
|
aAsObject = aAsObject.base
|
||||||
|
|
||||||
if aAsObject.kind == tyObject:
|
if aAsObject.kind == tyObject:
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,12 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||||
result.add mapTypeToAst(t.sons[0], info)
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
else:
|
else:
|
||||||
result = mapTypeToBracket("ref", mRef, t, info)
|
result = mapTypeToBracket("ref", mRef, t, info)
|
||||||
of tyVar: result = mapTypeToBracket("var", mVar, t, info)
|
of tyVar:
|
||||||
|
if inst:
|
||||||
|
result = newNodeX(nkVarTy)
|
||||||
|
result.add mapTypeToAst(t.sons[0], info)
|
||||||
|
else:
|
||||||
|
result = mapTypeToBracket("var", mVar, t, info)
|
||||||
of tyLent: result = mapTypeToBracket("lent", mBuiltinType, t, info)
|
of tyLent: result = mapTypeToBracket("lent", mBuiltinType, t, info)
|
||||||
of tySink: result = mapTypeToBracket("sink", mBuiltinType, t, info)
|
of tySink: result = mapTypeToBracket("sink", mBuiltinType, t, info)
|
||||||
of tySequence: result = mapTypeToBracket("seq", mSeq, t, info)
|
of tySequence: result = mapTypeToBracket("seq", mSeq, t, info)
|
||||||
|
|
|
||||||
|
|
@ -1553,6 +1553,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkFloatLit, info, t)
|
result = newNodeIT(nkFloatLit, info, t)
|
||||||
of tyCString, tyString:
|
of tyCString, tyString:
|
||||||
result = newNodeIT(nkStrLit, info, t)
|
result = newNodeIT(nkStrLit, info, t)
|
||||||
|
result.strVal = ""
|
||||||
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
|
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
|
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
|
||||||
result = newNodeIT(nkNilLit, info, t)
|
result = newNodeIT(nkNilLit, info, t)
|
||||||
|
|
|
||||||
|
|
@ -645,7 +645,6 @@ template replaceImpl(str: string, pattern: Regex,
|
||||||
let bounds = match.matchBounds
|
let bounds = match.matchBounds
|
||||||
result.add(str.substr(lastIdx, bounds.a - 1))
|
result.add(str.substr(lastIdx, bounds.a - 1))
|
||||||
let nextVal = replacement
|
let nextVal = replacement
|
||||||
assert(nextVal != nil)
|
|
||||||
result.add(nextVal)
|
result.add(nextVal)
|
||||||
|
|
||||||
lastIdx = bounds.b + 1
|
lastIdx = bounds.b + 1
|
||||||
|
|
|
||||||
|
|
@ -1280,15 +1280,13 @@ proc setLen*[T](s: var seq[T], newlen: Natural) {.
|
||||||
## sets the length of `s` to `newlen`.
|
## sets the length of `s` to `newlen`.
|
||||||
## ``T`` may be any sequence type.
|
## ``T`` may be any sequence type.
|
||||||
## If the current length is greater than the new length,
|
## If the current length is greater than the new length,
|
||||||
## ``s`` will be truncated. `s` cannot be nil! To initialize a sequence with
|
## ``s`` will be truncated.
|
||||||
## a size, use ``newSeq`` instead.
|
|
||||||
|
|
||||||
proc setLen*(s: var string, newlen: Natural) {.
|
proc setLen*(s: var string, newlen: Natural) {.
|
||||||
magic: "SetLengthStr", noSideEffect.}
|
magic: "SetLengthStr", noSideEffect.}
|
||||||
## sets the length of `s` to `newlen`.
|
## sets the length of `s` to `newlen`.
|
||||||
## If the current length is greater than the new length,
|
## If the current length is greater than the new length,
|
||||||
## ``s`` will be truncated. `s` cannot be nil! To initialize a string with
|
## ``s`` will be truncated.
|
||||||
## a size, use ``newString`` instead.
|
|
||||||
##
|
##
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## var myS = "Nim is great!!"
|
## var myS = "Nim is great!!"
|
||||||
|
|
@ -2414,6 +2412,7 @@ proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
|
||||||
if seqToPtr(x) == seqToPtr(y):
|
if seqToPtr(x) == seqToPtr(y):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
when not defined(nimNoNil):
|
||||||
if x.isNil or y.isNil:
|
if x.isNil or y.isNil:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
@ -4012,18 +4011,18 @@ proc addQuoted*[T](s: var string, x: T) =
|
||||||
|
|
||||||
when hasAlloc:
|
when hasAlloc:
|
||||||
# XXX: make these the default (or implement the NilObject optimization)
|
# XXX: make these the default (or implement the NilObject optimization)
|
||||||
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
|
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect, deprecated.} =
|
||||||
## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
|
## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
|
||||||
## ``x`` becomes ``@[y]``
|
## ``x`` becomes ``@[y]``
|
||||||
if x == nil: x = @[y]
|
if x == nil: x = @[y]
|
||||||
else: x.add(y)
|
else: x.add(y)
|
||||||
|
|
||||||
proc safeAdd*(x: var string, y: char) =
|
proc safeAdd*(x: var string, y: char) {.noSideEffect, deprecated.} =
|
||||||
## Adds ``y`` to ``x``. If ``x`` is ``nil`` it is initialized to ``""``
|
## Adds ``y`` to ``x``. If ``x`` is ``nil`` it is initialized to ``""``
|
||||||
if x == nil: x = ""
|
if x == nil: x = ""
|
||||||
x.add(y)
|
x.add(y)
|
||||||
|
|
||||||
proc safeAdd*(x: var string, y: string) =
|
proc safeAdd*(x: var string, y: string) {.noSideEffect, deprecated.} =
|
||||||
## Adds ``y`` to ``x`` unless ``x`` is not yet initalized; in that
|
## Adds ``y`` to ``x`` unless ``x`` is not yet initalized; in that
|
||||||
## case, ``x`` becomes ``y``
|
## case, ``x`` becomes ``y``
|
||||||
if x == nil: x = y
|
if x == nil: x = y
|
||||||
|
|
|
||||||
|
|
@ -22,21 +22,34 @@ proc resize(old: int): int {.inline.} =
|
||||||
|
|
||||||
proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
||||||
if a == b: return 0
|
if a == b: return 0
|
||||||
|
when defined(nimNoNil):
|
||||||
|
let alen = if a == nil: 0 else: a.len
|
||||||
|
let blen = if b == nil: 0 else: b.len
|
||||||
|
else:
|
||||||
if a == nil: return -1
|
if a == nil: return -1
|
||||||
if b == nil: return 1
|
if b == nil: return 1
|
||||||
let minlen = min(a.len, b.len)
|
let alen = a.len
|
||||||
|
let blen = b.len
|
||||||
|
let minlen = min(alen, blen)
|
||||||
if minlen > 0:
|
if minlen > 0:
|
||||||
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
result = a.len - b.len
|
result = alen - blen
|
||||||
else:
|
else:
|
||||||
result = a.len - b.len
|
result = alen - blen
|
||||||
|
|
||||||
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
||||||
if a == b: return true
|
if a == b: return true
|
||||||
|
when defined(nimNoNil):
|
||||||
|
let alen = if a == nil: 0 else: a.len
|
||||||
|
let blen = if b == nil: 0 else: b.len
|
||||||
|
else:
|
||||||
if a == nil or b == nil: return false
|
if a == nil or b == nil: return false
|
||||||
return a.len == b.len and
|
let alen = a.len
|
||||||
equalMem(addr(a.data), addr(b.data), a.len)
|
let blen = b.len
|
||||||
|
if alen == blen:
|
||||||
|
if alen == 0: return true
|
||||||
|
return equalMem(addr(a.data), addr(b.data), alen)
|
||||||
|
|
||||||
when declared(allocAtomic):
|
when declared(allocAtomic):
|
||||||
template allocStr(size: untyped): untyped =
|
template allocStr(size: untyped): untyped =
|
||||||
|
|
@ -101,9 +114,6 @@ proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
|
||||||
if str == nil: NimString(nil)
|
if str == nil: NimString(nil)
|
||||||
else: toNimStr(str, str.len)
|
else: toNimStr(str, str.len)
|
||||||
|
|
||||||
template wasMoved(x: NimString): bool = false
|
|
||||||
# (x.reserved and seqShallowFlag) != 0
|
|
||||||
|
|
||||||
proc copyString(src: NimString): NimString {.compilerRtl.} =
|
proc copyString(src: NimString): NimString {.compilerRtl.} =
|
||||||
if src != nil:
|
if src != nil:
|
||||||
if (src.reserved and seqShallowFlag) != 0:
|
if (src.reserved and seqShallowFlag) != 0:
|
||||||
|
|
@ -161,14 +171,16 @@ proc hashString(s: string): int {.compilerproc.} =
|
||||||
|
|
||||||
proc addChar(s: NimString, c: char): NimString =
|
proc addChar(s: NimString, c: char): NimString =
|
||||||
# is compilerproc!
|
# is compilerproc!
|
||||||
|
if s == nil:
|
||||||
|
result = rawNewStringNoInit(1)
|
||||||
|
result.len = 0
|
||||||
|
else:
|
||||||
result = s
|
result = s
|
||||||
if result.len >= result.space:
|
if result.len >= result.space:
|
||||||
let r = resize(result.space)
|
let r = resize(result.space)
|
||||||
result = cast[NimString](growObj(result,
|
result = cast[NimString](growObj(result,
|
||||||
sizeof(TGenericSeq) + r + 1))
|
sizeof(TGenericSeq) + r + 1))
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
elif wasMoved(s):
|
|
||||||
result = newOwnedString(s, s.len)
|
|
||||||
result.data[result.len] = c
|
result.data[result.len] = c
|
||||||
result.data[result.len+1] = '\0'
|
result.data[result.len+1] = '\0'
|
||||||
inc(result.len)
|
inc(result.len)
|
||||||
|
|
@ -205,7 +217,9 @@ proc addChar(s: NimString, c: char): NimString =
|
||||||
# s = rawNewString(0);
|
# s = rawNewString(0);
|
||||||
|
|
||||||
proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
|
proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
|
||||||
if dest.len + addlen <= dest.space and not wasMoved(dest):
|
if dest == nil:
|
||||||
|
result = rawNewStringNoInit(addlen)
|
||||||
|
elif dest.len + addlen <= dest.space:
|
||||||
result = dest
|
result = dest
|
||||||
else: # slow path:
|
else: # slow path:
|
||||||
var sp = max(resize(dest.space), dest.len + addlen)
|
var sp = max(resize(dest.space), dest.len + addlen)
|
||||||
|
|
@ -216,6 +230,7 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
|
||||||
# DO NOT UPDATE LEN YET: dest.len = newLen
|
# DO NOT UPDATE LEN YET: dest.len = newLen
|
||||||
|
|
||||||
proc appendString(dest, src: NimString) {.compilerproc, inline.} =
|
proc appendString(dest, src: NimString) {.compilerproc, inline.} =
|
||||||
|
if src != nil:
|
||||||
copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1)
|
copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1)
|
||||||
inc(dest.len, src.len)
|
inc(dest.len, src.len)
|
||||||
|
|
||||||
|
|
@ -226,8 +241,8 @@ proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
|
||||||
|
|
||||||
proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
|
proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
|
||||||
var n = max(newLen, 0)
|
var n = max(newLen, 0)
|
||||||
if wasMoved(s):
|
if s == nil:
|
||||||
result = newOwnedString(s, n)
|
result = mnewString(newLen)
|
||||||
elif n <= s.space:
|
elif n <= s.space:
|
||||||
result = s
|
result = s
|
||||||
else:
|
else:
|
||||||
|
|
@ -261,6 +276,18 @@ proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
|
||||||
GenericSeqSize))
|
GenericSeqSize))
|
||||||
result.reserved = r
|
result.reserved = r
|
||||||
|
|
||||||
|
proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.} =
|
||||||
|
if s == nil:
|
||||||
|
result = cast[PGenericSeq](newSeq(typ, 1))
|
||||||
|
result.len = 0
|
||||||
|
else:
|
||||||
|
result = s
|
||||||
|
if result.len >= result.space:
|
||||||
|
let r = resize(result.space)
|
||||||
|
result = cast[PGenericSeq](growObj(result, typ.base.size * r +
|
||||||
|
GenericSeqSize))
|
||||||
|
result.reserved = r
|
||||||
|
|
||||||
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
compilerRtl, inl.} =
|
compilerRtl, inl.} =
|
||||||
result = seq
|
result = seq
|
||||||
|
|
@ -301,6 +328,13 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
|
||||||
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
(newLen*%elemSize)), (result.len-%newLen) *% elemSize)
|
||||||
result.len = newLen
|
result.len = newLen
|
||||||
|
|
||||||
|
proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
|
||||||
|
compilerRtl.} =
|
||||||
|
if s == nil:
|
||||||
|
result = cast[PGenericSeq](newSeq(typ, newLen))
|
||||||
|
else:
|
||||||
|
result = setLengthSeq(s, typ.base.size, newLen)
|
||||||
|
|
||||||
# --------------- other string routines ----------------------------------
|
# --------------- other string routines ----------------------------------
|
||||||
proc add*(result: var string; x: int64) =
|
proc add*(result: var string; x: int64) =
|
||||||
let base = result.len
|
let base = result.len
|
||||||
|
|
|
||||||
51
tests/array/tarraycons_ptr_generic.nim
Normal file
51
tests/array/tarraycons_ptr_generic.nim
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
discard """
|
||||||
|
output: '''apple
|
||||||
|
banana
|
||||||
|
Fruit
|
||||||
|
2
|
||||||
|
4
|
||||||
|
3
|
||||||
|
none
|
||||||
|
skin
|
||||||
|
paper
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
type
|
||||||
|
Fruit = object of RootObj
|
||||||
|
name: string
|
||||||
|
Apple = object of Fruit
|
||||||
|
Banana = object of Fruit
|
||||||
|
|
||||||
|
var
|
||||||
|
ir = Fruit(name: "Fruit")
|
||||||
|
ia = Apple(name: "apple")
|
||||||
|
ib = Banana(name: "banana")
|
||||||
|
|
||||||
|
let x = [ia.addr, ib.addr, ir.addr]
|
||||||
|
for c in x: echo c.name
|
||||||
|
|
||||||
|
type
|
||||||
|
Vehicle[T] = object of RootObj
|
||||||
|
tire: T
|
||||||
|
Car[T] = object of Vehicle[T]
|
||||||
|
Bike[T] = object of Vehicle[T]
|
||||||
|
|
||||||
|
var v = Vehicle[int](tire: 3)
|
||||||
|
var c = Car[int](tire: 4)
|
||||||
|
var b = Bike[int](tire: 2)
|
||||||
|
|
||||||
|
let y = [b.addr, c.addr, v.addr]
|
||||||
|
for c in y: echo c.tire
|
||||||
|
|
||||||
|
type
|
||||||
|
Book[T] = ref object of RootObj
|
||||||
|
cover: T
|
||||||
|
Hard[T] = ref object of Book[T]
|
||||||
|
Soft[T] = ref object of Book[T]
|
||||||
|
|
||||||
|
var bn = Book[string](cover: "none")
|
||||||
|
var hs = Hard[string](cover: "skin")
|
||||||
|
var bp = Soft[string](cover: "paper")
|
||||||
|
|
||||||
|
let z = [bn, hs, bp]
|
||||||
|
for c in z: echo c.cover
|
||||||
17
tests/array/tarraycons_ptr_generic2.nim
Normal file
17
tests/array/tarraycons_ptr_generic2.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
file: "tarraycons_ptr_generic2.nim"
|
||||||
|
line: 17
|
||||||
|
errormsg: "type mismatch: got <ptr Hard[system.string]> but expected 'Book[system.string]'"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Book[T] = ref object of RootObj
|
||||||
|
cover: T
|
||||||
|
Hard[T] = ref object of Book[T]
|
||||||
|
Soft[T] = ref object of Book[T]
|
||||||
|
|
||||||
|
var bn = Book[string](cover: "none")
|
||||||
|
var hs = Hard[string](cover: "skin")
|
||||||
|
var bp = Soft[string](cover: "paper")
|
||||||
|
|
||||||
|
let z = [bn, hs.addr, bp]
|
||||||
|
|
@ -3,7 +3,7 @@ discard """
|
||||||
exitcode: 1
|
exitcode: 1
|
||||||
"""
|
"""
|
||||||
|
|
||||||
proc returnsNil(): string = return nil
|
proc returnsNil(): ref int = return nil
|
||||||
|
|
||||||
iterator fields*(a, b: int): int =
|
iterator fields*(a, b: int): int =
|
||||||
if a == b:
|
if a == b:
|
||||||
|
|
@ -17,6 +17,6 @@ proc main(): string =
|
||||||
result = ""
|
result = ""
|
||||||
for i in fields(0, 1):
|
for i in fields(0, 1):
|
||||||
let x = returnsNil()
|
let x = returnsNil()
|
||||||
result &= "string literal " & $x
|
result &= "string literal " & $x[]
|
||||||
|
|
||||||
echo main()
|
echo main()
|
||||||
|
|
|
||||||
|
|
@ -209,7 +209,7 @@ proc `$`*(data: Tcommandline_results): string =
|
||||||
|
|
||||||
# - Parse code
|
# - Parse code
|
||||||
|
|
||||||
template raise_or_quit(exception, message: expr): stmt {.immediate.} =
|
template raise_or_quit(exception, message: untyped) =
|
||||||
## Avoids repeating if check based on the default quit_on_failure variable.
|
## Avoids repeating if check based on the default quit_on_failure variable.
|
||||||
##
|
##
|
||||||
## As a special case, if message has a zero length the call to quit won't
|
## As a special case, if message has a zero length the call to quit won't
|
||||||
|
|
@ -230,15 +230,15 @@ template run_custom_proc(parsed_parameter: Tparsed_parameter,
|
||||||
##
|
##
|
||||||
## Pass in the string of the parameter triggering the call. If the
|
## Pass in the string of the parameter triggering the call. If the
|
||||||
if not custom_validator.isNil:
|
if not custom_validator.isNil:
|
||||||
except:
|
try:
|
||||||
raise_or_quit(ValueError, ("Couldn't run custom proc for " &
|
|
||||||
"parameter $1:\n$2" % [escape(parameter),
|
|
||||||
getCurrentExceptionMsg()]))
|
|
||||||
let message = custom_validator(parameter, parsed_parameter)
|
let message = custom_validator(parameter, parsed_parameter)
|
||||||
if not message.isNil and message.len > 0:
|
if not message.isNil and message.len > 0:
|
||||||
raise_or_quit(ValueError, ("Failed to validate value for " &
|
raise_or_quit(ValueError, ("Failed to validate value for " &
|
||||||
"parameter $1:\n$2" % [escape(parameter), message]))
|
"parameter $1:\n$2" % [escape(parameter), message]))
|
||||||
|
except:
|
||||||
|
raise_or_quit(ValueError, ("Couldn't run custom proc for " &
|
||||||
|
"parameter $1:\n$2" % [escape(parameter),
|
||||||
|
getCurrentExceptionMsg()]))
|
||||||
|
|
||||||
proc parse_parameter(quit_on_failure: bool, param, value: string,
|
proc parse_parameter(quit_on_failure: bool, param, value: string,
|
||||||
param_kind: Tparam_kind): Tparsed_parameter =
|
param_kind: Tparam_kind): Tparsed_parameter =
|
||||||
|
|
|
||||||
25
tests/system/tnilconcats.nim
Normal file
25
tests/system/tnilconcats.nim
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
discard """
|
||||||
|
output: '''@[nil, nil, nil, nil, nil, nil, nil, "meh"]'''
|
||||||
|
exitcode: "0"
|
||||||
|
"""
|
||||||
|
|
||||||
|
when true:
|
||||||
|
var ab: string
|
||||||
|
ab &= "more"
|
||||||
|
|
||||||
|
doAssert ab == "more"
|
||||||
|
|
||||||
|
var x: seq[string]
|
||||||
|
|
||||||
|
setLen(x, 7)
|
||||||
|
|
||||||
|
x.add "meh"
|
||||||
|
|
||||||
|
var s: string
|
||||||
|
var z = "abc"
|
||||||
|
var zz: string
|
||||||
|
s &= "foo" & z & zz
|
||||||
|
|
||||||
|
doAssert s == "fooabc"
|
||||||
|
|
||||||
|
echo x
|
||||||
|
|
@ -51,3 +51,59 @@ import strutils
|
||||||
let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
|
let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
|
||||||
doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']"
|
doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']"
|
||||||
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
||||||
|
|
||||||
|
proc takes(c: cstring) =
|
||||||
|
doAssert c == ""
|
||||||
|
|
||||||
|
proc testm() =
|
||||||
|
var x: string
|
||||||
|
# nil is mapped to "":
|
||||||
|
takes(x)
|
||||||
|
|
||||||
|
testm()
|
||||||
|
|
||||||
|
# nil tests
|
||||||
|
var xx: seq[string]
|
||||||
|
var yy: string
|
||||||
|
doAssert xx == @[]
|
||||||
|
doAssert yy == ""
|
||||||
|
|
||||||
|
proc bar(arg: cstring): void =
|
||||||
|
doAssert arg[0] == '\0'
|
||||||
|
|
||||||
|
proc baz(arg: openarray[char]): void =
|
||||||
|
doAssert arg.len == 0
|
||||||
|
|
||||||
|
proc stringCompare(): void =
|
||||||
|
var a,b,c,d,e,f,g: string
|
||||||
|
a.add 'a'
|
||||||
|
doAssert a == "a"
|
||||||
|
b.add "bee"
|
||||||
|
doAssert b == "bee"
|
||||||
|
b.add g
|
||||||
|
doAssert b == "bee"
|
||||||
|
c.add 123.456
|
||||||
|
doAssert c == "123.456"
|
||||||
|
d.add 123456
|
||||||
|
doAssert d == "123456"
|
||||||
|
|
||||||
|
doAssert e == ""
|
||||||
|
doAssert "" == e
|
||||||
|
doAssert nil == e
|
||||||
|
doAssert e == nil
|
||||||
|
doAssert f == g
|
||||||
|
doAssert "" == ""
|
||||||
|
doAssert "" == nil
|
||||||
|
doAssert nil == ""
|
||||||
|
|
||||||
|
g.setLen(10)
|
||||||
|
doAssert g == "\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
doAssert "" != "\0\0\0\0\0\0\0\0\0\0"
|
||||||
|
|
||||||
|
var nilstring: string
|
||||||
|
bar(nilstring)
|
||||||
|
baz(nilstring)
|
||||||
|
|
||||||
|
stringCompare()
|
||||||
|
static:
|
||||||
|
stringCompare()
|
||||||
18
tests/typerel/t7600_1.nim
Normal file
18
tests/typerel/t7600_1.nim
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "type mismatch: got <Thin[system.int]>"
|
||||||
|
nimout: '''t7600_1.nim(18, 6) Error: type mismatch: got <Thin[system.int]>
|
||||||
|
but expected one of:
|
||||||
|
proc test[T](x: Paper[T])
|
||||||
|
|
||||||
|
expression: test tn'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Paper[T] = ref object of RootObj
|
||||||
|
thickness: T
|
||||||
|
Thin[T] = object of Paper[T]
|
||||||
|
|
||||||
|
proc test[T](x: Paper[T]) = discard
|
||||||
|
|
||||||
|
var tn = Thin[int]()
|
||||||
|
test tn
|
||||||
17
tests/typerel/t7600_2.nim
Normal file
17
tests/typerel/t7600_2.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
discard """
|
||||||
|
errormsg: "type mismatch: got <Thin>"
|
||||||
|
nimout: '''t7600_2.nim(17, 6) Error: type mismatch: got <Thin>
|
||||||
|
but expected one of:
|
||||||
|
proc test(x: Paper)
|
||||||
|
|
||||||
|
expression: test tn'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
type
|
||||||
|
Paper = ref object of RootObj
|
||||||
|
Thin = object of Paper
|
||||||
|
|
||||||
|
proc test(x: Paper) = discard
|
||||||
|
|
||||||
|
var tn = Thin()
|
||||||
|
test tn
|
||||||
|
|
@ -128,7 +128,7 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
|
||||||
stdout.write("\n")
|
stdout.write("\n")
|
||||||
stdout.flushFile()
|
stdout.flushFile()
|
||||||
|
|
||||||
proc processFile(pattern; filename: string) =
|
proc processFile(pattern; filename: string; counter: var int) =
|
||||||
var filenameShown = false
|
var filenameShown = false
|
||||||
template beforeHighlight =
|
template beforeHighlight =
|
||||||
if not filenameShown and optVerbose notin options and not oneline:
|
if not filenameShown and optVerbose notin options and not oneline:
|
||||||
|
|
@ -166,6 +166,7 @@ proc processFile(pattern; filename: string) =
|
||||||
var wholeMatch = buffer.substr(t.first, t.last)
|
var wholeMatch = buffer.substr(t.first, t.last)
|
||||||
|
|
||||||
beforeHighlight()
|
beforeHighlight()
|
||||||
|
inc counter
|
||||||
if optReplace notin options:
|
if optReplace notin options:
|
||||||
highlight(buffer, wholeMatch, "", t, filename, line, showRepl=false)
|
highlight(buffer, wholeMatch, "", t, filename, line, showRepl=false)
|
||||||
else:
|
else:
|
||||||
|
|
@ -241,17 +242,17 @@ proc styleInsensitive(s: string): string =
|
||||||
addx()
|
addx()
|
||||||
else: addx()
|
else: addx()
|
||||||
|
|
||||||
proc walker(pattern; dir: string) =
|
proc walker(pattern; dir: string; counter: var int) =
|
||||||
for kind, path in walkDir(dir):
|
for kind, path in walkDir(dir):
|
||||||
case kind
|
case kind
|
||||||
of pcFile:
|
of pcFile:
|
||||||
if extensions.len == 0 or path.hasRightExt(extensions):
|
if extensions.len == 0 or path.hasRightExt(extensions):
|
||||||
processFile(pattern, path)
|
processFile(pattern, path, counter)
|
||||||
of pcDir:
|
of pcDir:
|
||||||
if optRecursive in options:
|
if optRecursive in options:
|
||||||
walker(pattern, path)
|
walker(pattern, path, counter)
|
||||||
else: discard
|
else: discard
|
||||||
if existsFile(dir): processFile(pattern, dir)
|
if existsFile(dir): processFile(pattern, dir, counter)
|
||||||
|
|
||||||
proc writeHelp() =
|
proc writeHelp() =
|
||||||
stdout.write(Usage)
|
stdout.write(Usage)
|
||||||
|
|
@ -321,6 +322,7 @@ if optStdin in options:
|
||||||
if pattern.len == 0:
|
if pattern.len == 0:
|
||||||
writeHelp()
|
writeHelp()
|
||||||
else:
|
else:
|
||||||
|
var counter = 0
|
||||||
if filenames.len == 0:
|
if filenames.len == 0:
|
||||||
filenames.add(os.getCurrentDir())
|
filenames.add(os.getCurrentDir())
|
||||||
if optRegex notin options:
|
if optRegex notin options:
|
||||||
|
|
@ -332,7 +334,7 @@ else:
|
||||||
pattern = "\\i " & pattern
|
pattern = "\\i " & pattern
|
||||||
let pegp = peg(pattern)
|
let pegp = peg(pattern)
|
||||||
for f in items(filenames):
|
for f in items(filenames):
|
||||||
walker(pegp, f)
|
walker(pegp, f, counter)
|
||||||
else:
|
else:
|
||||||
var reflags = {reStudy, reExtended}
|
var reflags = {reStudy, reExtended}
|
||||||
if optIgnoreStyle in options:
|
if optIgnoreStyle in options:
|
||||||
|
|
@ -343,5 +345,6 @@ else:
|
||||||
reflags.incl reIgnoreCase
|
reflags.incl reIgnoreCase
|
||||||
let rep = re(pattern, reflags)
|
let rep = re(pattern, reflags)
|
||||||
for f in items(filenames):
|
for f in items(filenames):
|
||||||
walker(rep, f)
|
walker(rep, f, counter)
|
||||||
|
if not oneline:
|
||||||
|
stdout.write($counter & " matches\n")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue