Merge branch 'devel' into araq-fixes-6960
This commit is contained in:
commit
4c702d5ab2
10 changed files with 191 additions and 111 deletions
|
|
@ -274,9 +274,10 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
|
|||
|
||||
proc processPath(path: string, info: TLineInfo,
|
||||
notRelativeToProj = false): string =
|
||||
let p = if notRelativeToProj or os.isAbsolute(path) or
|
||||
'$' in path:
|
||||
let p = if os.isAbsolute(path) or '$' in path:
|
||||
path
|
||||
elif notRelativeToProj:
|
||||
getCurrentDir() / path
|
||||
else:
|
||||
options.gProjectPath / path
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -11,38 +11,39 @@ import ast, renderer, strutils, msgs, options, idents, os
|
|||
|
||||
import nimblecmd
|
||||
|
||||
const
|
||||
considerParentDirs = not defined(noParentProjects)
|
||||
considerNimbleDirs = not defined(noNimbleDirs)
|
||||
when false:
|
||||
const
|
||||
considerParentDirs = not defined(noParentProjects)
|
||||
considerNimbleDirs = not defined(noNimbleDirs)
|
||||
|
||||
proc findInNimbleDir(pkg, subdir, dir: string): string =
|
||||
var best = ""
|
||||
var bestv = ""
|
||||
for k, p in os.walkDir(dir, relative=true):
|
||||
if k == pcDir and p.len > pkg.len+1 and
|
||||
p[pkg.len] == '-' and p.startsWith(pkg):
|
||||
let (_, a) = getPathVersion(p)
|
||||
if bestv.len == 0 or bestv < a:
|
||||
bestv = a
|
||||
best = dir / p
|
||||
proc findInNimbleDir(pkg, subdir, dir: string): string =
|
||||
var best = ""
|
||||
var bestv = ""
|
||||
for k, p in os.walkDir(dir, relative=true):
|
||||
if k == pcDir and p.len > pkg.len+1 and
|
||||
p[pkg.len] == '-' and p.startsWith(pkg):
|
||||
let (_, a) = getPathVersion(p)
|
||||
if bestv.len == 0 or bestv < a:
|
||||
bestv = a
|
||||
best = dir / p
|
||||
|
||||
if best.len > 0:
|
||||
var f: File
|
||||
if open(f, best / changeFileExt(pkg, ".nimble-link")):
|
||||
# the second line contains what we're interested in, see:
|
||||
# https://github.com/nim-lang/nimble#nimble-link
|
||||
var override = ""
|
||||
discard readLine(f, override)
|
||||
discard readLine(f, override)
|
||||
close(f)
|
||||
if not override.isAbsolute():
|
||||
best = best / override
|
||||
else:
|
||||
best = override
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
let res = addFileExt(best / f, "nim")
|
||||
if best.len > 0 and fileExists(res):
|
||||
result = res
|
||||
if best.len > 0:
|
||||
var f: File
|
||||
if open(f, best / changeFileExt(pkg, ".nimble-link")):
|
||||
# the second line contains what we're interested in, see:
|
||||
# https://github.com/nim-lang/nimble#nimble-link
|
||||
var override = ""
|
||||
discard readLine(f, override)
|
||||
discard readLine(f, override)
|
||||
close(f)
|
||||
if not override.isAbsolute():
|
||||
best = best / override
|
||||
else:
|
||||
best = override
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
let res = addFileExt(best / f, "nim")
|
||||
if best.len > 0 and fileExists(res):
|
||||
result = res
|
||||
|
||||
const stdlibDirs = [
|
||||
"pure", "core", "arch",
|
||||
|
|
@ -51,65 +52,66 @@ const stdlibDirs = [
|
|||
"wrappers", "wrappers/linenoise",
|
||||
"windows", "posix", "js"]
|
||||
|
||||
proc resolveDollar(project, source, pkg, subdir: string; info: TLineInfo): string =
|
||||
template attempt(a) =
|
||||
let x = addFileExt(a, "nim")
|
||||
if fileExists(x): return x
|
||||
when false:
|
||||
proc resolveDollar(project, source, pkg, subdir: string; info: TLineInfo): string =
|
||||
template attempt(a) =
|
||||
let x = addFileExt(a, "nim")
|
||||
if fileExists(x): return x
|
||||
|
||||
case pkg
|
||||
of "stdlib":
|
||||
if subdir.len == 0:
|
||||
return options.libpath
|
||||
case pkg
|
||||
of "stdlib":
|
||||
if subdir.len == 0:
|
||||
return options.libpath
|
||||
else:
|
||||
for candidate in stdlibDirs:
|
||||
attempt(options.libpath / candidate / subdir)
|
||||
of "root":
|
||||
let root = project.splitFile.dir
|
||||
if subdir.len == 0:
|
||||
return root
|
||||
else:
|
||||
attempt(root / subdir)
|
||||
else:
|
||||
for candidate in stdlibDirs:
|
||||
attempt(options.libpath / candidate / subdir)
|
||||
of "root":
|
||||
let root = project.splitFile.dir
|
||||
if subdir.len == 0:
|
||||
return root
|
||||
else:
|
||||
attempt(root / subdir)
|
||||
else:
|
||||
when considerParentDirs:
|
||||
var p = parentDir(source.splitFile.dir)
|
||||
# support 'import $karax':
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
when considerParentDirs:
|
||||
var p = parentDir(source.splitFile.dir)
|
||||
# support 'import $karax':
|
||||
let f = if subdir.len == 0: pkg else: subdir
|
||||
|
||||
while p.len > 0:
|
||||
let dir = p / pkg
|
||||
if dirExists(dir):
|
||||
attempt(dir / f)
|
||||
# 2nd attempt: try to use 'karax/karax'
|
||||
attempt(dir / pkg / f)
|
||||
# 3rd attempt: try to use 'karax/src/karax'
|
||||
attempt(dir / "src" / f)
|
||||
attempt(dir / "src" / pkg / f)
|
||||
p = parentDir(p)
|
||||
while p.len > 0:
|
||||
let dir = p / pkg
|
||||
if dirExists(dir):
|
||||
attempt(dir / f)
|
||||
# 2nd attempt: try to use 'karax/karax'
|
||||
attempt(dir / pkg / f)
|
||||
# 3rd attempt: try to use 'karax/src/karax'
|
||||
attempt(dir / "src" / f)
|
||||
attempt(dir / "src" / pkg / f)
|
||||
p = parentDir(p)
|
||||
|
||||
when considerNimbleDirs:
|
||||
if not options.gNoNimblePath:
|
||||
var nimbleDir = getEnv("NIMBLE_DIR")
|
||||
if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
|
||||
result = findInNimbleDir(pkg, subdir, nimbleDir / "pkgs")
|
||||
if result.len > 0: return result
|
||||
when not defined(windows):
|
||||
result = findInNimbleDir(pkg, subdir, "/opt/nimble/pkgs")
|
||||
when considerNimbleDirs:
|
||||
if not options.gNoNimblePath:
|
||||
var nimbleDir = getEnv("NIMBLE_DIR")
|
||||
if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
|
||||
result = findInNimbleDir(pkg, subdir, nimbleDir / "pkgs")
|
||||
if result.len > 0: return result
|
||||
when not defined(windows):
|
||||
result = findInNimbleDir(pkg, subdir, "/opt/nimble/pkgs")
|
||||
if result.len > 0: return result
|
||||
|
||||
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
||||
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
||||
if result.isNil: result = ""
|
||||
proc scriptableImport(pkg, sub: string; info: TLineInfo): string =
|
||||
result = resolveDollar(gProjectFull, info.toFullPath(), pkg, sub, info)
|
||||
if result.isNil: result = ""
|
||||
|
||||
proc lookupPackage(pkg, subdir: PNode): string =
|
||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||
case pkg.kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
result = scriptableImport(pkg.strVal, sub, pkg.info)
|
||||
of nkIdent:
|
||||
result = scriptableImport(pkg.ident.s, sub, pkg.info)
|
||||
else:
|
||||
localError(pkg.info, "package name must be an identifier or string literal")
|
||||
result = ""
|
||||
proc lookupPackage(pkg, subdir: PNode): string =
|
||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||
case pkg.kind
|
||||
of nkStrLit, nkRStrLit, nkTripleStrLit:
|
||||
result = scriptableImport(pkg.strVal, sub, pkg.info)
|
||||
of nkIdent:
|
||||
result = scriptableImport(pkg.ident.s, sub, pkg.info)
|
||||
else:
|
||||
localError(pkg.info, "package name must be an identifier or string literal")
|
||||
result = ""
|
||||
|
||||
proc getModuleName*(n: PNode): string =
|
||||
# This returns a short relative module name without the nim extension
|
||||
|
|
@ -136,23 +138,34 @@ proc getModuleName*(n: PNode): string =
|
|||
n.sons[1] = n.sons[2]
|
||||
n.sons.setLen(2)
|
||||
return getModuleName(n.sons[0])
|
||||
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
|
||||
if n0.kind == nkIdent and n0.ident.s == "/":
|
||||
result = lookupPackage(n1[1], n[2])
|
||||
else:
|
||||
localError(n.info, "only '/' supported with $package notation")
|
||||
result = ""
|
||||
when false:
|
||||
if n1.kind == nkPrefix and n1[0].kind == nkIdent and n1[0].ident.s == "$":
|
||||
if n0.kind == nkIdent and n0.ident.s == "/":
|
||||
result = lookupPackage(n1[1], n[2])
|
||||
else:
|
||||
localError(n.info, "only '/' supported with $package notation")
|
||||
result = ""
|
||||
else:
|
||||
let modname = getModuleName(n[2])
|
||||
if $n1 == "std":
|
||||
template attempt(a) =
|
||||
let x = addFileExt(a, "nim")
|
||||
if fileExists(x): return x
|
||||
for candidate in stdlibDirs:
|
||||
attempt(options.libpath / candidate / modname)
|
||||
|
||||
# hacky way to implement 'x / y /../ z':
|
||||
result = getModuleName(n1)
|
||||
result.add renderTree(n0, {renderNoComments})
|
||||
result.add getModuleName(n[2])
|
||||
result.add modname
|
||||
of nkPrefix:
|
||||
if n.sons[0].kind == nkIdent and n.sons[0].ident.s == "$":
|
||||
result = lookupPackage(n[1], nil)
|
||||
else:
|
||||
# hacky way to implement 'x / y /../ z':
|
||||
result = renderTree(n, {renderNoComments}).replace(" ")
|
||||
when false:
|
||||
if n.sons[0].kind == nkIdent and n.sons[0].ident.s == "$":
|
||||
result = lookupPackage(n[1], nil)
|
||||
else:
|
||||
discard
|
||||
# hacky way to implement 'x / y /../ z':
|
||||
result = renderTree(n, {renderNoComments}).replace(" ")
|
||||
of nkDotExpr:
|
||||
result = renderTree(n, {renderNoComments}).replace(".", "/")
|
||||
of nkImportAs:
|
||||
|
|
|
|||
|
|
@ -657,15 +657,16 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
|
|||
result = qualifiedLookUp(c, n, {checkUndeclared})
|
||||
|
||||
proc semCustomPragma(c: PContext, n: PNode): PNode =
|
||||
assert(n.kind in nkPragmaCallKinds + {nkIdent})
|
||||
|
||||
if n.kind == nkIdent:
|
||||
result = newTree(nkCall, n)
|
||||
elif n.kind == nkExprColonExpr:
|
||||
# pragma: arg -> pragma(arg)
|
||||
result = newTree(nkCall, n[0], n[1])
|
||||
else:
|
||||
elif n.kind in nkPragmaCallKinds + {nkIdent}:
|
||||
result = n
|
||||
else:
|
||||
invalidPragma(n)
|
||||
return n
|
||||
|
||||
let r = c.semOverloadedCall(c, result, n, {skTemplate}, {})
|
||||
if r.isNil or sfCustomPragma notin r[0].sym.flags:
|
||||
|
|
|
|||
|
|
@ -124,6 +124,15 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
|||
else:
|
||||
break
|
||||
|
||||
proc effectProblem(f, a: PType; result: var string) =
|
||||
if f.kind == tyProc and a.kind == tyProc:
|
||||
if tfThread in f.flags and tfThread notin a.flags:
|
||||
result.add "\n This expression is not GC-safe. Annotate the " &
|
||||
"proc with {.gcsafe.} to get extended error information."
|
||||
elif tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
|
||||
result.add "\n This expression can have side effects. Annotate the " &
|
||||
"proc with {.noSideEffect.} to get extended error information."
|
||||
|
||||
proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||
(TPreferedDesc, string) =
|
||||
var prefer = preferName
|
||||
|
|
@ -158,15 +167,20 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
|||
if err.firstMismatch != 0 and n.len > 2:
|
||||
add(candidates, " first type mismatch at position: " & $err.firstMismatch &
|
||||
"\n required type: ")
|
||||
var wanted, got: PType = nil
|
||||
if err.firstMismatch < err.sym.typ.len:
|
||||
candidates.add typeToString(err.sym.typ.sons[err.firstMismatch])
|
||||
wanted = err.sym.typ.sons[err.firstMismatch]
|
||||
candidates.add typeToString(wanted)
|
||||
else:
|
||||
candidates.add "none"
|
||||
if err.firstMismatch < n.len:
|
||||
candidates.add "\n but expression '"
|
||||
candidates.add renderTree(n[err.firstMismatch])
|
||||
candidates.add "' is of type: "
|
||||
candidates.add typeToString(n[err.firstMismatch].typ)
|
||||
got = n[err.firstMismatch].typ
|
||||
candidates.add typeToString(got)
|
||||
if wanted != nil and got != nil:
|
||||
effectProblem(wanted, got, candidates)
|
||||
candidates.add "\n"
|
||||
elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
|
||||
add(candidates, "for a 'var' type a variable needs to be passed, but '" &
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ proc semDiscard(c: PContext, n: PNode): PNode =
|
|||
checkSonsLen(n, 1)
|
||||
if n.sons[0].kind != nkEmpty:
|
||||
n.sons[0] = semExprWithType(c, n.sons[0])
|
||||
if isEmptyType(n.sons[0].typ) or n.sons[0].typ.kind == tyNone:
|
||||
if isEmptyType(n.sons[0].typ) or n.sons[0].typ.kind == tyNone or n.sons[0].kind == nkTypeOfExpr:
|
||||
localError(n.info, errInvalidDiscard)
|
||||
|
||||
proc semBreakOrContinue(c: PContext, n: PNode): PNode =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue