added nimfix tool
This commit is contained in:
parent
4c870fc293
commit
bf557a7cdb
9 changed files with 156 additions and 11 deletions
|
|
@ -139,7 +139,7 @@ proc ropecg(m: BModule, frmt: TFormatStr, args: varargs[PRope]): PRope =
|
||||||
if i - 1 >= start:
|
if i - 1 >= start:
|
||||||
app(result, substr(frmt, start, i - 1))
|
app(result, substr(frmt, start, i - 1))
|
||||||
|
|
||||||
const compileTimeRopeFmt = not defined(booting)
|
const compileTimeRopeFmt = false
|
||||||
|
|
||||||
when compileTimeRopeFmt:
|
when compileTimeRopeFmt:
|
||||||
import macros
|
import macros
|
||||||
|
|
@ -186,7 +186,7 @@ when compileTimeRopeFmt:
|
||||||
while s[i] in IdentChars: inc i
|
while s[i] in IdentChars: inc i
|
||||||
yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0)
|
yield (kind: ffSym, value: substr(s, j, i-1), intValue: 0)
|
||||||
start = i
|
start = i
|
||||||
else: nil
|
else: discard
|
||||||
|
|
||||||
while i < length:
|
while i < length:
|
||||||
if s[i] != '$' and s[i] != '#': inc i
|
if s[i] != '$' and s[i] != '#': inc i
|
||||||
|
|
@ -201,7 +201,7 @@ when compileTimeRopeFmt:
|
||||||
## the compilation of nimrod itself or will the macro execution time
|
## the compilation of nimrod itself or will the macro execution time
|
||||||
## offset the gains?
|
## offset the gains?
|
||||||
result = newCall(bindSym"ropeConcat")
|
result = newCall(bindSym"ropeConcat")
|
||||||
for frag in fmtStringFragments(fmt.strVal):
|
for frag in fmtStringFragments(fmt):
|
||||||
case frag.kind
|
case frag.kind
|
||||||
of ffSym:
|
of ffSym:
|
||||||
result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value)))
|
result.add(newCall(bindSym"cgsym", m, newStrLitNode(frag.value)))
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,7 @@ proc addOverloadableSymAt*(scope: PScope, fn: PSym) =
|
||||||
if fn.kind notin OverloadableSyms:
|
if fn.kind notin OverloadableSyms:
|
||||||
internalError(fn.info, "addOverloadableSymAt")
|
internalError(fn.info, "addOverloadableSymAt")
|
||||||
return
|
return
|
||||||
var check = strTableGet(scope.symbols, fn.name)
|
let check = strTableGet(scope.symbols, fn.name)
|
||||||
if check != nil and check.kind notin OverloadableSyms:
|
if check != nil and check.kind notin OverloadableSyms:
|
||||||
wrongRedefinition(fn.info, fn.name.s)
|
wrongRedefinition(fn.info, fn.name.s)
|
||||||
else:
|
else:
|
||||||
|
|
@ -187,12 +187,32 @@ proc addInterfaceOverloadableSymAt*(c: PContext, scope: PScope, sym: PSym) =
|
||||||
addOverloadableSymAt(scope, sym)
|
addOverloadableSymAt(scope, sym)
|
||||||
addInterfaceDeclAux(c, sym)
|
addInterfaceDeclAux(c, sym)
|
||||||
|
|
||||||
|
when defined(nimfix):
|
||||||
|
import strutils
|
||||||
|
|
||||||
|
# when we cannot find the identifier, retry with a changed identifer:
|
||||||
|
proc altSpelling(x: PIdent): PIdent =
|
||||||
|
case x.s[0]
|
||||||
|
of 'A'..'Z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
|
||||||
|
of 'a'..'z': result = getIdent(toLower(x.s[0]) & x.s.substr(1))
|
||||||
|
else: result = x
|
||||||
|
|
||||||
|
template fixSpelling(n: PNode; ident: PIdent; op: expr) =
|
||||||
|
let alt = ident.altSpelling
|
||||||
|
result = op(c, alt).skipAlias(n)
|
||||||
|
if result != nil:
|
||||||
|
prettybase.replaceDeprecated(n.info, ident, alt)
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
template fixSpelling(n: PNode; ident: PIdent; op: expr) = discard
|
||||||
|
|
||||||
proc lookUp*(c: PContext, n: PNode): PSym =
|
proc lookUp*(c: PContext, n: PNode): PSym =
|
||||||
# Looks up a symbol. Generates an error in case of nil.
|
# Looks up a symbol. Generates an error in case of nil.
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
result = searchInScopes(c, n.ident).skipAlias(n)
|
result = searchInScopes(c, n.ident).skipAlias(n)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
fixSpelling(n, n.ident, searchInScopes)
|
||||||
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
localError(n.info, errUndeclaredIdentifier, n.ident.s)
|
||||||
result = errorSym(c, n)
|
result = errorSym(c, n)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
|
|
@ -201,6 +221,7 @@ proc lookUp*(c: PContext, n: PNode): PSym =
|
||||||
var ident = considerQuotedIdent(n)
|
var ident = considerQuotedIdent(n)
|
||||||
result = searchInScopes(c, ident).skipAlias(n)
|
result = searchInScopes(c, ident).skipAlias(n)
|
||||||
if result == nil:
|
if result == nil:
|
||||||
|
fixSpelling(n, ident, searchInScopes)
|
||||||
localError(n.info, errUndeclaredIdentifier, ident.s)
|
localError(n.info, errUndeclaredIdentifier, ident.s)
|
||||||
result = errorSym(c, n)
|
result = errorSym(c, n)
|
||||||
else:
|
else:
|
||||||
|
|
@ -220,6 +241,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||||
var ident = considerQuotedIdent(n)
|
var ident = considerQuotedIdent(n)
|
||||||
result = searchInScopes(c, ident).skipAlias(n)
|
result = searchInScopes(c, ident).skipAlias(n)
|
||||||
if result == nil and checkUndeclared in flags:
|
if result == nil and checkUndeclared in flags:
|
||||||
|
fixSpelling(n, ident, searchInScopes)
|
||||||
localError(n.info, errUndeclaredIdentifier, ident.s)
|
localError(n.info, errUndeclaredIdentifier, ident.s)
|
||||||
result = errorSym(c, n)
|
result = errorSym(c, n)
|
||||||
elif checkAmbiguity in flags and result != nil and
|
elif checkAmbiguity in flags and result != nil and
|
||||||
|
|
@ -244,6 +266,7 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
|
||||||
else:
|
else:
|
||||||
result = strTableGet(m.tab, ident).skipAlias(n)
|
result = strTableGet(m.tab, ident).skipAlias(n)
|
||||||
if result == nil and checkUndeclared in flags:
|
if result == nil and checkUndeclared in flags:
|
||||||
|
fixSpelling(n.sons[1], ident, searchInScopes)
|
||||||
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
|
localError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
|
||||||
result = errorSym(c, n.sons[1])
|
result = errorSym(c, n.sons[1])
|
||||||
elif n.sons[1].kind == nkSym:
|
elif n.sons[1].kind == nkSym:
|
||||||
|
|
|
||||||
|
|
@ -21,3 +21,4 @@ define:useStdoutAsStdmsg
|
||||||
|
|
||||||
cs:partial
|
cs:partial
|
||||||
#define:useNodeIds
|
#define:useNodeIds
|
||||||
|
symbol:nimfix
|
||||||
|
|
|
||||||
97
compiler/nimfix.nim
Normal file
97
compiler/nimfix.nim
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# The Nim Compiler
|
||||||
|
# (c) Copyright 2014 Andreas Rumpf
|
||||||
|
#
|
||||||
|
# See the file "copying.txt", included in this
|
||||||
|
# distribution, for details about the copyright.
|
||||||
|
#
|
||||||
|
|
||||||
|
## Nimfix is a tool that helps to convert old-style Nimrod code to Nim code.
|
||||||
|
|
||||||
|
import strutils, os, parseopt
|
||||||
|
import options, commands, modules, sem, passes, passaux, pretty, msgs, nimconf,
|
||||||
|
extccomp, condsyms
|
||||||
|
|
||||||
|
const Usage = """
|
||||||
|
Nimfix - Tool to patch Nim code
|
||||||
|
Usage:
|
||||||
|
nimfix [options] projectflie.nim
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--overwriteFiles:on|off overwrite the original nim files.
|
||||||
|
DEFAULT is ON!
|
||||||
|
--checkExtern:on|off style check also extern names
|
||||||
|
--styleCheck:none|confirm|auto performs style checking for identifiers
|
||||||
|
and suggests an alternative spelling. If
|
||||||
|
'auto', it automatically corrects the
|
||||||
|
spelling. If 'confirm' it asks the user.
|
||||||
|
|
||||||
|
In addition, all command line options of Nim are supported.
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc mainCommand =
|
||||||
|
#msgs.gErrorMax = high(int) # do not stop after first error
|
||||||
|
registerPass verbosePass
|
||||||
|
registerPass semPass
|
||||||
|
registerPass prettyPass
|
||||||
|
gCmd = cmdPretty
|
||||||
|
compileProject()
|
||||||
|
pretty.overwriteFiles()
|
||||||
|
|
||||||
|
proc processCmdLine*(pass: TCmdLinePass, cmd: string) =
|
||||||
|
var p = parseopt.initOptParser(cmd)
|
||||||
|
var argsCount = 0
|
||||||
|
while true:
|
||||||
|
parseopt.next(p)
|
||||||
|
case p.kind
|
||||||
|
of cmdEnd: break
|
||||||
|
of cmdLongoption, cmdShortOption:
|
||||||
|
case p.key.normalize
|
||||||
|
of "overwritefiles":
|
||||||
|
case p.val.normalize
|
||||||
|
of "on": gOverWrite = true
|
||||||
|
of "off": gOverWrite = false
|
||||||
|
else: localError(gCmdLineInfo, errOnOrOffExpected)
|
||||||
|
of "checkextern":
|
||||||
|
case p.val.normalize
|
||||||
|
of "on": gCheckExtern = true
|
||||||
|
of "off": gCheckExtern = false
|
||||||
|
else: localError(gCmdLineInfo, errOnOrOffExpected)
|
||||||
|
of "stylecheck":
|
||||||
|
case p.val.normalize
|
||||||
|
of "none": gStyleCheck = StyleCheck.None
|
||||||
|
of "confirm": gStyleCheck = StyleCheck.Confirm
|
||||||
|
of "auto": gStyleCheck = StyleCheck.Auto
|
||||||
|
else: localError(gCmdLineInfo, errGenerated,
|
||||||
|
"'none', 'confirm' or 'auto' expected")
|
||||||
|
else:
|
||||||
|
processSwitch(pass, p)
|
||||||
|
of cmdArgument:
|
||||||
|
if processArgument(pass, p, argsCount): break
|
||||||
|
|
||||||
|
proc handleCmdLine() =
|
||||||
|
if paramCount() == 0:
|
||||||
|
stdout.writeln(Usage)
|
||||||
|
else:
|
||||||
|
processCmdLine(passCmd1, "")
|
||||||
|
if gProjectName != "":
|
||||||
|
try:
|
||||||
|
gProjectFull = canonicalizePath(gProjectName)
|
||||||
|
except OSError:
|
||||||
|
gProjectFull = gProjectName
|
||||||
|
var p = splitFile(gProjectFull)
|
||||||
|
gProjectPath = p.dir
|
||||||
|
gProjectName = p.name
|
||||||
|
else:
|
||||||
|
gProjectPath = getCurrentDir()
|
||||||
|
loadConfigs(DefaultConfig) # load all config files
|
||||||
|
# now process command line arguments again, because some options in the
|
||||||
|
# command line can overwite the config file's settings
|
||||||
|
extccomp.initVars()
|
||||||
|
processCmdLine(passCmd2, "")
|
||||||
|
mainCommand()
|
||||||
|
|
||||||
|
condsyms.initDefines()
|
||||||
|
defineSymbol "nimfix"
|
||||||
|
handleCmdline()
|
||||||
16
compiler/nimfix.nim.cfg
Normal file
16
compiler/nimfix.nim.cfg
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Special configuration file for the Nim project
|
||||||
|
# gc:markAndSweep
|
||||||
|
|
||||||
|
hint[XDeclaredButNotUsed]:off
|
||||||
|
path:"$projectPath/.."
|
||||||
|
|
||||||
|
path:"$lib/packages/docutils"
|
||||||
|
|
||||||
|
define:useStdoutAsStdmsg
|
||||||
|
symbol:nimfix
|
||||||
|
define:nimfix
|
||||||
|
|
||||||
|
cs:partial
|
||||||
|
#define:useNodeIds
|
||||||
|
define:booting
|
||||||
|
define:noDocgen
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
#
|
#
|
||||||
|
|
||||||
import ast, msgs, strutils
|
import ast, msgs, strutils, idents
|
||||||
|
|
||||||
type
|
type
|
||||||
TSourceFile* = object
|
TSourceFile* = object
|
||||||
|
|
@ -41,7 +41,7 @@ proc differ*(line: string, a, b: int, x: string): bool =
|
||||||
let y = line[a..b]
|
let y = line[a..b]
|
||||||
result = cmpIgnoreStyle(y, x) == 0 and y != x
|
result = cmpIgnoreStyle(y, x) == 0 and y != x
|
||||||
|
|
||||||
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
|
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PIdent) =
|
||||||
loadFile(info)
|
loadFile(info)
|
||||||
|
|
||||||
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
|
let line = gSourceFiles[info.fileIndex].lines[info.line-1]
|
||||||
|
|
@ -53,7 +53,10 @@ proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
|
||||||
if line[first] == '`': inc first
|
if line[first] == '`': inc first
|
||||||
|
|
||||||
let last = first+identLen(line, first)-1
|
let last = first+identLen(line, first)-1
|
||||||
if cmpIgnoreStyle(line[first..last], oldSym.name.s) == 0:
|
if cmpIgnoreStyle(line[first..last], oldSym.s) == 0:
|
||||||
var x = line.substr(0, first-1) & newSym.name.s & line.substr(last+1)
|
var x = line.substr(0, first-1) & newSym.s & line.substr(last+1)
|
||||||
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
system.shallowCopy(gSourceFiles[info.fileIndex].lines[info.line-1], x)
|
||||||
gSourceFiles[info.fileIndex].dirty = true
|
gSourceFiles[info.fileIndex].dirty = true
|
||||||
|
|
||||||
|
proc replaceDeprecated*(info: TLineInfo; oldSym, newSym: PSym) =
|
||||||
|
replaceDeprecated(info, oldSym.name, newSym.name)
|
||||||
|
|
|
||||||
|
|
@ -1482,6 +1482,9 @@ proc argtypeMatches*(c: PContext, f, a: PType): bool =
|
||||||
|
|
||||||
include suggest
|
include suggest
|
||||||
|
|
||||||
|
when not declared(tests):
|
||||||
|
template tests(s: stmt) {.immediate.} = discard
|
||||||
|
|
||||||
tests:
|
tests:
|
||||||
var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
|
var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1138,7 +1138,7 @@ template needsAdditionalCopy(n): expr =
|
||||||
not c.isTemp(dest) and not fitsRegister(n.typ)
|
not c.isTemp(dest) and not fitsRegister(n.typ)
|
||||||
|
|
||||||
proc skipDeref(n: PNode): PNode =
|
proc skipDeref(n: PNode): PNode =
|
||||||
result = if n.kind in {nkDerefExpr, nkHiddenDeref}: n.sons[0] else n
|
result = if n.kind in {nkDerefExpr, nkHiddenDeref}: n.sons[0] else: n
|
||||||
|
|
||||||
proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
|
proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
|
||||||
dest, idx, value: TRegister) =
|
dest, idx, value: TRegister) =
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,9 @@ cc = gcc
|
||||||
arm.linux.gcc.exe = "arm-linux-gcc"
|
arm.linux.gcc.exe = "arm-linux-gcc"
|
||||||
arm.linux.gcc.linkerexe = "arm-linux-gcc"
|
arm.linux.gcc.linkerexe = "arm-linux-gcc"
|
||||||
|
|
||||||
|
@if not nimfix:
|
||||||
cs:partial
|
cs:partial
|
||||||
|
@end
|
||||||
|
|
||||||
path="$lib/core"
|
path="$lib/core"
|
||||||
path="$lib/pure"
|
path="$lib/pure"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue