added nimfix tool

This commit is contained in:
Araq 2014-09-05 01:16:48 +02:00
commit bf557a7cdb
9 changed files with 156 additions and 11 deletions

View file

@ -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)))

View file

@ -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:
@ -214,12 +235,13 @@ type
TLookupFlag* = enum TLookupFlag* = enum
checkAmbiguity, checkUndeclared checkAmbiguity, checkUndeclared
proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = proc qualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
case n.kind case n.kind
of nkIdent, nkAccQuoted: of nkIdent, nkAccQuoted:
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:

View file

@ -21,3 +21,4 @@ define:useStdoutAsStdmsg
cs:partial cs:partial
#define:useNodeIds #define:useNodeIds
symbol:nimfix

97
compiler/nimfix.nim Normal file
View 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
View 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

View file

@ -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)

View file

@ -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())

View file

@ -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) =

View file

@ -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"
cs:partial @if not nimfix:
cs:partial
@end
path="$lib/core" path="$lib/core"
path="$lib/pure" path="$lib/pure"