123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- #
- #
- # The Nim Compiler
- # (c) Copyright 2017 Contributors
- #
- # See the file "copying.txt", included in this
- # distribution, for details about the copyright.
- #
- import ast, renderer, strutils, msgs, options, idents, os, lineinfos,
- pathutils
- proc getModuleName*(conf: ConfigRef; 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(conf, n.strVal, toFullPath(conf, n.info).splitFile().dir)
- except ValueError:
- localError(conf, 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]
- 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(conf, n[2])
- # hacky way to implement 'x / y /../ z':
- result = getModuleName(conf, n1)
- result.add renderTree(n0, {renderNoComments}).replace(" ")
- result.add modname
- of nkPrefix:
- when false:
- if n[0].kind == nkIdent and n[0].ident.s == "$":
- result = lookupPackage(n[1], nil)
- else:
- discard
- # hacky way to implement 'x / y /../ z':
- result = renderTree(n, {renderNoComments}).replace(" ")
- of nkDotExpr:
- localError(conf, n.info, warnDeprecated, "using '.' instead of '/' in import paths is deprecated")
- result = renderTree(n, {renderNoComments}).replace(".", "/")
- of nkImportAs:
- result = getModuleName(conf, n[0])
- else:
- localError(conf, n.info, "invalid module name: '$1'" % n.renderTree)
- result = ""
- proc checkModuleName*(conf: ConfigRef; n: PNode; doLocalError=true): FileIndex =
- # This returns the full canonical path for a given module import
- let modulename = getModuleName(conf, n)
- let fullPath = findModule(conf, modulename, toFullPath(conf, n.info))
- if fullPath.isEmpty:
- if doLocalError:
- let m = if modulename.len > 0: modulename else: $n
- localError(conf, n.info, "cannot open file: " & m)
- result = InvalidFileIdx
- else:
- result = fileInfoIdx(conf, fullPath)
- proc mangleModuleName*(conf: ConfigRef; path: AbsoluteFile): string =
- ## Mangle a relative module path to avoid path and symbol collisions.
- ##
- ## Used by backends that need to generate intermediary files from Nim modules.
- ## This is needed because the compiler uses a flat cache file hierarchy.
- ##
- ## Example:
- ## `foo-#head/../bar` becomes `@foo-@hhead@s..@sbar`
- "@m" & relativeTo(path, conf.projectPath).string.multiReplace(
- {$os.DirSep: "@s", $os.AltSep: "@s", "#": "@h", "@": "@@", ":": "@c"})
- proc demangleModuleName*(path: string): string =
- ## Demangle a relative module path.
- result = path.multiReplace({"@@": "@", "@h": "#", "@s": "/", "@m": "", "@c": ":"})
|