Files
Nim/compiler/modulepaths.nim

78 lines
2.7 KiB
Nim

#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import ast, renderer, gorgeimpl, strutils, msgs, options, idents, ospaths
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
# e.g. like "system", "importer" or "somepath/module"
# The proc won't perform any checks that the path is actually valid
case n.kind
of nkStrLit, nkRStrLit, nkTripleStrLit:
try:
result = pathSubs(n.strVal, n.info.toFullPath().splitFile().dir)
except ValueError:
localError(n.info, "invalid path: " & n.strVal)
result = n.strVal
of nkIdent:
result = n.ident.s
of nkSym:
result = n.sym.name.s
of nkInfix:
let n0 = n[0]
let n1 = n[1]
if n0.kind == nkIdent and n0.ident.id == getIdent("as").id:
# XXX hack ahead:
n.kind = nkImportAs
n.sons[0] = n.sons[1]
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 = ""
else:
# hacky way to implement 'x / y /../ z':
result = getModuleName(n1)
result.add renderTree(n0, {renderNoComments})
result.add getModuleName(n[2])
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(" ")
of nkDotExpr:
result = renderTree(n, {renderNoComments}).replace(".", "/")
of nkImportAs:
result = getModuleName(n.sons[0])
else:
localError(n.info, errGenerated, "invalid module name: '$1'" % n.renderTree)
result = ""
proc checkModuleName*(n: PNode; doLocalError=true): int32 =
# This returns the full canonical path for a given module import
let modulename = n.getModuleName
let fullPath = findModule(modulename, n.info.toFullPath)
if fullPath.len == 0:
if doLocalError:
localError(n.info, errCannotOpenFile, modulename)
result = InvalidFileIDX
else:
result = fullPath.fileInfoIdx