made nimresolve part of the compiler
This commit is contained in:
parent
6a3288a60e
commit
29c075299d
7 changed files with 100 additions and 193 deletions
|
|
@ -7,8 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
## Module that implements ``gorge`` for the compiler as well as
|
## Module that implements ``gorge`` for the compiler.
|
||||||
## the scriptable import mechanism.
|
|
||||||
|
|
||||||
import msgs, securehash, os, osproc, streams, strutils, options
|
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
|
result = p.readOutput
|
||||||
except IOError, OSError:
|
except IOError, OSError:
|
||||||
result = ("", -1)
|
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))
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,103 @@
|
||||||
#
|
#
|
||||||
|
#
|
||||||
|
# The Nim Compiler
|
||||||
|
# (c) Copyright 2017 Contributors
|
||||||
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# 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 =
|
proc lookupPackage(pkg, subdir: PNode): string =
|
||||||
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
let sub = if subdir != nil: renderTree(subdir, {renderNoComments}).replace(" ") else: ""
|
||||||
|
|
|
||||||
|
|
@ -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: TThing, b: TUnit[T]) is instantiated and not
|
||||||
# method collide[T](a: TUnit[T], b: TThing)! This means we need to
|
# 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
|
# *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
|
# to avoid subtle problems, the call remains ambiguous and needs to
|
||||||
# be disambiguated by the programmer; this way the right generic is
|
# be disambiguated by the programmer; this way the right generic is
|
||||||
# instantiated.
|
# instantiated.
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ type
|
||||||
# a distrinct type
|
# a distrinct type
|
||||||
typedescMatched*: bool
|
typedescMatched*: bool
|
||||||
isNoCall*: bool # misused for generic type instantiations C[T]
|
isNoCall*: bool # misused for generic type instantiations C[T]
|
||||||
|
mutabilityProblem*: uint8 # tyVar mismatch
|
||||||
inferredTypes: seq[PType] # inferred types during the current signature
|
inferredTypes: seq[PType] # inferred types during the current signature
|
||||||
# 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
|
||||||
|
|
@ -66,7 +67,6 @@ type
|
||||||
# or when the explain pragma is used. may be
|
# or when the explain pragma is used. may be
|
||||||
# triggered with an idetools command in the
|
# triggered with an idetools command in the
|
||||||
# future.
|
# future.
|
||||||
mutabilityProblem*: uint8 # tyVar mismatch
|
|
||||||
inheritancePenalty: int # to prefer closest father object type
|
inheritancePenalty: int # to prefer closest father object type
|
||||||
|
|
||||||
TTypeRelFlag* = enum
|
TTypeRelFlag* = enum
|
||||||
|
|
|
||||||
2
koch.nim
2
koch.nim
|
|
@ -263,7 +263,7 @@ proc buildTools(latest: bool) =
|
||||||
nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim"
|
nimexec "c -o:" & nimgrepExe & " tools/nimgrep.nim"
|
||||||
when defined(windows): buildVccTool()
|
when defined(windows): buildVccTool()
|
||||||
|
|
||||||
nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim"
|
#nimexec "c -o:" & ("bin/nimresolve".exe) & " tools/nimresolve.nim"
|
||||||
|
|
||||||
buildNimble(latest)
|
buildNimble(latest)
|
||||||
|
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -1,8 +1,7 @@
|
||||||
version 1.0 battle plan
|
version 1.0 battle plan
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
- make nimresolve part of the Nim compiler and add support for
|
- make FlowVar compatible to Futures
|
||||||
'import staticExec()'
|
|
||||||
- remove 'mod x' type rule
|
- remove 'mod x' type rule
|
||||||
- implement x[^1] differently, no compiler magic
|
- implement x[^1] differently, no compiler magic
|
||||||
- fix "high priority" bugs
|
- fix "high priority" bugs
|
||||||
|
|
|
||||||
|
|
@ -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()
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue