'nimrod pretty' command: next steps
This commit is contained in:
parent
d6d665b0c0
commit
6810a0e3e3
2 changed files with 107 additions and 43 deletions
|
|
@ -15,7 +15,8 @@ import
|
||||||
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
||||||
cgen, jsgen, json, nversion,
|
cgen, jsgen, json, nversion,
|
||||||
platform, nimconf, importer, passaux, depends, evals, types, idgen,
|
platform, nimconf, importer, passaux, depends, evals, types, idgen,
|
||||||
tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists
|
tables, docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists,
|
||||||
|
pretty
|
||||||
|
|
||||||
from magicsys import SystemModule, resetSysTypes
|
from magicsys import SystemModule, resetSysTypes
|
||||||
|
|
||||||
|
|
@ -162,12 +163,18 @@ proc commandEval(exp: string) =
|
||||||
var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
|
var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
|
||||||
evalNim(echoExp.parseString, makeStdinModule())
|
evalNim(echoExp.parseString, makeStdinModule())
|
||||||
|
|
||||||
proc CommandPretty =
|
proc CommandPrettyOld =
|
||||||
var projectFile = addFileExt(mainCommandArg(), NimExt)
|
var projectFile = addFileExt(mainCommandArg(), NimExt)
|
||||||
var module = parseFile(projectFile.fileInfoIdx)
|
var module = parseFile(projectFile.fileInfoIdx)
|
||||||
if module != nil:
|
if module != nil:
|
||||||
renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
|
renderModule(module, getOutFile(mainCommandArg(), "pretty." & NimExt))
|
||||||
|
|
||||||
|
proc CommandPretty =
|
||||||
|
semanticPasses()
|
||||||
|
registerPass(prettyPass)
|
||||||
|
compileProject()
|
||||||
|
pretty.overwriteFiles()
|
||||||
|
|
||||||
proc CommandScan =
|
proc CommandScan =
|
||||||
var f = addFileExt(mainCommandArg(), nimExt)
|
var f = addFileExt(mainCommandArg(), nimExt)
|
||||||
var stream = LLStreamOpen(f, fmRead)
|
var stream = LLStreamOpen(f, fmRead)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
## to convert Nimrod code into a consistent style.
|
## to convert Nimrod code into a consistent style.
|
||||||
|
|
||||||
import
|
import
|
||||||
os, options, ast, astalgo, msgs, ropes, idents, passes, importer
|
strutils, os, options, ast, astalgo, msgs, ropes, idents, passes, pegs,
|
||||||
|
intsets
|
||||||
|
|
||||||
type
|
type
|
||||||
TGen = object of TPassContext
|
TGen = object of TPassContext
|
||||||
|
|
@ -23,54 +24,110 @@ type
|
||||||
dirty: bool
|
dirty: bool
|
||||||
fullpath: string
|
fullpath: string
|
||||||
|
|
||||||
proc addSourceLine(fileIdx: int32, line: string) =
|
var
|
||||||
fileInfos[fileIdx].lines.add line
|
gSourceFiles: seq[TSourceFile]
|
||||||
|
|
||||||
proc sourceLine(i: TLineInfo): PRope =
|
proc loadFile(info: TLineInfo) =
|
||||||
if i.fileIndex < 0: return nil
|
let i = info.fileIndex
|
||||||
|
if i >= gSourceFiles.len:
|
||||||
|
gSourceFiles.setLen(i)
|
||||||
|
gSourceFiles[i].lines = @[]
|
||||||
|
let path = info.toFullPath
|
||||||
|
gSourceFiles[i].fullpath = path
|
||||||
|
# we want to die here for EIO:
|
||||||
|
for line in lines(path):
|
||||||
|
gSourceFiles[i].lines.add(line)
|
||||||
|
|
||||||
if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0:
|
proc overwriteFiles*() =
|
||||||
try:
|
for i in 0 .. high(gSourceFiles):
|
||||||
for line in lines(i.toFullPath):
|
if not gSourceFiles[i].dirty: continue
|
||||||
addSourceLine i.fileIndex, line.string
|
var f = open(gSourceFiles[i].fullpath.changeFileExt(".pretty.nim"), fmWrite)
|
||||||
except EIO:
|
for line in gSourceFiles[i].lines:
|
||||||
discard
|
f.writeln(line)
|
||||||
InternalAssert i.fileIndex < fileInfos.len
|
f.close
|
||||||
# can happen if the error points to EOF:
|
|
||||||
if i.line > fileInfos[i.fileIndex].lines.len: return nil
|
|
||||||
|
|
||||||
result = fileInfos[i.fileIndex].lines[i.line-1]
|
proc beautifyName(s: string, k: TSymKind): string =
|
||||||
|
result = newStringOfCap(s.len)
|
||||||
|
var i = 0
|
||||||
|
case k
|
||||||
|
of skType, skGenericParam:
|
||||||
|
# skip leading 'T'
|
||||||
|
if s[0] == 'T' and s[1] in {'A'..'Z'}:
|
||||||
|
i = 1
|
||||||
|
result.add toUpper(s[i])
|
||||||
|
of skConst, skEnumField:
|
||||||
|
# for 'const' we keep how it's spelt; either upper case or lower case:
|
||||||
|
result.add s[0]
|
||||||
|
else:
|
||||||
|
result.add toLower(s[0])
|
||||||
|
inc i
|
||||||
|
let allUpper = allCharsInSet(s, {'A'..'Z', '0'..'9', '_'})
|
||||||
|
while i < s.len:
|
||||||
|
if s[i] == '_':
|
||||||
|
inc i
|
||||||
|
result.add toUpper(s[i])
|
||||||
|
elif allUpper:
|
||||||
|
result.add toLower(s[i])
|
||||||
|
else:
|
||||||
|
result.add s[i]
|
||||||
|
inc i
|
||||||
|
|
||||||
proc addDependencyAux(importing, imported: string) =
|
const
|
||||||
appf(gDotGraph, "$1 -> $2;$n", [toRope(importing), toRope(imported)])
|
Letters = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
|
||||||
# s1 -> s2_4[label="[0-9]"];
|
|
||||||
|
|
||||||
proc addDotDependency(c: PPassContext, n: PNode): PNode =
|
proc identLen(line: string, start: int): int =
|
||||||
|
while start+result < line.len and line[start+result] in Letters:
|
||||||
|
inc result
|
||||||
|
|
||||||
|
proc differ(line: string, a, b: int, x: string): bool =
|
||||||
|
var j = 0
|
||||||
|
for i in a..b:
|
||||||
|
if line[i] != x[j]: return true
|
||||||
|
inc j
|
||||||
|
return false
|
||||||
|
|
||||||
|
var cannotRename = initIntSet()
|
||||||
|
|
||||||
|
proc processSym(c: PPassContext, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
var g = PGen(c)
|
var g = PGen(c)
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
|
if n.info.fileIndex < 0: return
|
||||||
|
let s = n.sym
|
||||||
|
# operators stay as they are:
|
||||||
|
if s.kind == skTemp or s.name.s[0] notin Letters: return
|
||||||
|
|
||||||
of nkTypeSection:
|
if s.id in cannotRename: return
|
||||||
# we need to figure out whether the PType or the TType should become
|
|
||||||
# Type. The other then is either TypePtr/TypeRef or TypeDesc.
|
|
||||||
|
|
||||||
of nkImportStmt:
|
let newName = beautifyName(s.name.s, n.sym.kind)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
|
||||||
var imported = getModuleName(n.sons[i])
|
loadFile(n.info)
|
||||||
addDependencyAux(g.module.name.s, imported)
|
|
||||||
of nkFromStmt, nkImportExceptStmt:
|
let line = gSourceFiles[n.info.fileIndex].lines[n.info.line-1]
|
||||||
var imported = getModuleName(n.sons[0])
|
var first = n.info.col.int - len(s.name.s)
|
||||||
addDependencyAux(g.module.name.s, imported)
|
if line[first] == '`': inc first
|
||||||
of nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr:
|
|
||||||
for i in countup(0, sonsLen(n) - 1): discard addDotDependency(c, n.sons[i])
|
if {sfImportc, sfExportc} * s.flags != {}:
|
||||||
|
# careful, we must ensure the resulting name still matches the external
|
||||||
|
# name:
|
||||||
|
if newName != s.name.s and newName != s.loc.r.ropeToStr:
|
||||||
|
Message(n.info, errGenerated,
|
||||||
|
"cannot rename $# to $# due to external name" % [s.name.s, newName])
|
||||||
|
cannotRename.incl(s.id)
|
||||||
|
return
|
||||||
|
let last = first+identLen(line, first)-1
|
||||||
|
if last-first+1 != newName.len or differ(line, first, last, newName):
|
||||||
|
var x = line.subStr(0, first-1) & newName & line.substr(last+1)
|
||||||
|
# the WinAPI module is full of 'TX = X' which after the substitution
|
||||||
|
# becomes 'X = X'. We remove those lines:
|
||||||
|
if x.match(peg"\s* {\ident} \s* '=' \s* y$1 ('#' .*)?"):
|
||||||
|
x = ""
|
||||||
|
system.shallowCopy(gSourceFiles[n.info.fileIndex].lines[n.info.line-1], x)
|
||||||
|
gSourceFiles[n.info.fileIndex].dirty = true
|
||||||
else:
|
else:
|
||||||
nil
|
for i in 0 .. <n.safeLen:
|
||||||
|
discard processSym(c, n.sons[i])
|
||||||
proc generateRefactorScript*(project: string) =
|
|
||||||
writeRope(ropef("digraph $1 {$n$2}$n", [
|
|
||||||
toRope(changeFileExt(extractFileName(project), "")), gDotGraph]),
|
|
||||||
changeFileExt(project, "dot"))
|
|
||||||
|
|
||||||
proc myOpen(module: PSym): PPassContext =
|
proc myOpen(module: PSym): PPassContext =
|
||||||
var g: PGen
|
var g: PGen
|
||||||
|
|
@ -78,5 +135,5 @@ proc myOpen(module: PSym): PPassContext =
|
||||||
g.module = module
|
g.module = module
|
||||||
result = g
|
result = g
|
||||||
|
|
||||||
const prettyPass* = makePass(open = myOpen, process = addDotDependency)
|
const prettyPass* = makePass(open = myOpen, process = processSym)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue