made nimresolve part of the compiler

This commit is contained in:
Andreas Rumpf
2017-10-29 15:40:50 +01:00
parent 6a3288a60e
commit 29c075299d
7 changed files with 100 additions and 193 deletions

View File

@@ -7,8 +7,7 @@
# distribution, for details about the copyright.
#
## Module that implements ``gorge`` for the compiler as well as
## the scriptable import mechanism.
## Module that implements ``gorge`` for the compiler.
import msgs, securehash, os, osproc, streams, strutils, options
@@ -56,28 +55,3 @@ proc opGorge*(cmd, input, cache: string, info: TLineInfo): (string, int) =
result = p.readOutput
except IOError, OSError:
result = ("", -1)
proc scriptableImport*(pkg, subdir: string; info: TLineInfo): string =
var cmd = getConfigVar("resolver.exe")
if cmd.len == 0: cmd = "nimresolve"
else: cmd = quoteShell(cmd)
cmd.add " --source:"
cmd.add quoteShell(info.toFullPath())
cmd.add " --stdlib:"
cmd.add quoteShell(options.libpath)
cmd.add " --project:"
cmd.add quoteShell(gProjectFull)
if subdir.len != 0:
cmd.add " --subdir:"
cmd.add quoteShell(subdir)
if options.gNoNimblePath:
cmd.add " --nonimblepath"
cmd.add ' '
cmd.add quoteShell(pkg)
let (res, exitCode) = opGorge(cmd, "", cmd, info)
if exitCode == 0:
result = res.strip()
elif res.len > 0:
localError(info, res)
else:
localError(info, "cannot resolve: " & (pkg / subdir))

View File

@@ -1,9 +1,103 @@
#
#
# The Nim Compiler
# (c) Copyright 2017 Contributors
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
import ast, renderer, gorgeimpl, strutils, msgs, options, idents, ospaths
import ast, renderer, strutils, msgs, options, idents, os
import nimblecmd
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
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",
"pure/collections",
"pure/concurrency", "impure",
"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
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:
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)
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)
proc lookupPackage(pkg, subdir: PNode): string =
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""

View File

@@ -27,7 +27,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
# method collide[T](a: TThing, b: TUnit[T]) is instantiated and not
# method collide[T](a: TUnit[T], b: TThing)! This means we need to
# *instantiate* every candidate! However, we don't keep more than 2-3
# candidated around so we cannot implement that for now. So in order
# candidates around so we cannot implement that for now. So in order
# to avoid subtle problems, the call remains ambiguous and needs to
# be disambiguated by the programmer; this way the right generic is
# instantiated.

View File

@@ -55,6 +55,7 @@ type
# a distrinct type
typedescMatched*: bool
isNoCall*: bool # misused for generic type instantiations C[T]
mutabilityProblem*: uint8 # tyVar mismatch
inferredTypes: seq[PType] # inferred types during the current signature
# matching. they will be reset if the matching
# is not successful. may replace the bindings
@@ -66,7 +67,6 @@ type
# or when the explain pragma is used. may be
# triggered with an idetools command in the
# future.
mutabilityProblem*: uint8 # tyVar mismatch
inheritancePenalty: int # to prefer closest father object type
TTypeRelFlag* = enum

View File

@@ -263,7 +263,7 @@ proc buildTools(latest: bool) =
nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim"
when defined(windows): buildVccTool()
nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim"
#nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim"
buildNimble(latest)

View File

@@ -1,8 +1,7 @@
version 1.0 battle plan
=======================
- make nimresolve part of the Nim compiler and add support for
'import staticExec()'
- make FlowVar compatible to Futures
- remove 'mod x' type rule
- implement x[^1] differently, no compiler magic
- fix "high priority" bugs

View File

@@ -1,160 +0,0 @@
#
#
# The Nim Compiler
# (c) Copyright 2017 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## Standard tool that resolves import paths.
import
os, strutils, parseopt
import "../compiler/nimblecmd"
# You can change these constants to build you own adapted resolver.
const
considerParentDirs = not defined(noParentProjects)
considerNimbleDirs = not defined(noNimbleDirs)
const
Version = "1.0"
Usage = "nimresolve - Nim Resolve Package Path Version " & Version & """
(c) 2017 Andreas Rumpf
Usage:
nimresolve [options] package
Options:
--source:FILE the file that requests to resolve 'package'
--stdlib:PATH the path to use for the standard library
--project:FILE the main '.nim' file that was passed to the Nim compiler
--subdir:EXPR the subdir part in: 'import $pkg / subdir'
--noNimblePath do not search the Nimble path to resolve the package
"""
proc writeHelp() =
stdout.write(Usage)
stdout.flushFile()
quit(0)
proc writeVersion() =
stdout.write(Version & "\n")
stdout.flushFile()
quit(0)
type
Task = object
source, stdlib, subdir, project, pkg: string
noNimblePath: bool
proc findInNimbleDir(t: Task; dir: string): bool =
var best = ""
var bestv = ""
for k, p in os.walkDir(dir, relative=true):
if k == pcDir and p.len > t.pkg.len+1 and
p[t.pkg.len] == '-' and p.startsWith(t.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(t.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 t.subdir.len == 0: t.pkg else: t.subdir
let res = addFileExt(best / f, "nim")
if best.len > 0 and fileExists(res):
echo res
result = true
const stdlibDirs = [
"pure", "core", "arch",
"pure/collections",
"pure/concurrency", "impure",
"wrappers", "wrappers/linenoise",
"windows", "posix", "js"]
proc resolve(t: Task) =
template attempt(a) =
let x = addFileExt(a, "nim")
if fileExists(x):
echo x
return
case t.pkg
of "stdlib":
if t.subdir.len == 0:
echo t.stdlib
return
else:
for candidate in stdlibDirs:
attempt(t.stdlib / candidate / t.subdir)
of "root":
let root = t.project.splitFile.dir
if t.subdir.len == 0:
echo root
return
else:
attempt(root / t.subdir)
else:
when considerParentDirs:
var p = parentDir(t.source.splitFile.dir)
# support 'import $karax':
let f = if t.subdir.len == 0: t.pkg else: t.subdir
while p.len > 0:
let dir = p / t.pkg
if dirExists(dir):
attempt(dir / f)
# 2nd attempt: try to use 'karax/karax'
attempt(dir / t.pkg / f)
# 3rd attempt: try to use 'karax/src/karax'
attempt(dir / "src" / f)
attempt(dir / "src" / t.pkg / f)
p = parentDir(p)
when considerNimbleDirs:
if not t.noNimblePath:
var nimbleDir = getEnv("NIMBLE_DIR")
if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
if findInNimbleDir(t, nimbleDir / "pkgs"): return
when not defined(windows):
if findInNimbleDir(t, "/opt/nimble/pkgs"): return
quit "cannot resolve: " & (t.pkg / t.subdir)
proc main =
var t: Task
t.subdir = ""
for kind, key, val in getopt():
case kind
of cmdArgument:
t.pkg = key
of cmdLongoption, cmdShortOption:
case normalize(key)
of "source": t.source = val
of "stdlib": t.stdlib = val
of "project": t.project = val
of "subdir": t.subdir = val
of "nonimblepath": t.noNimblePath = true
of "help", "h": writeHelp()
of "version", "v": writeVersion()
else: writeHelp()
of cmdEnd: assert(false) # cannot happen
if t.pkg.len == 0:
quit "[Error] no package to resolve."
resolve(t)
main()