diff options
-rwxr-xr-x | compiler/c2nim/clex.nim | 8 | ||||
-rwxr-xr-x | compiler/commands.nim | 10 | ||||
-rwxr-xr-x | compiler/lexer.nim | 8 | ||||
-rwxr-xr-x | compiler/main.nim | 2 | ||||
-rwxr-xr-x | compiler/msgs.nim | 65 | ||||
-rwxr-xr-x | compiler/nimrod.nim | 4 | ||||
-rwxr-xr-x | compiler/options.nim | 7 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 2 | ||||
-rwxr-xr-x | compiler/sigmatch.nim | 2 |
9 files changed, 61 insertions, 47 deletions
diff --git a/compiler/c2nim/clex.nim b/compiler/c2nim/clex.nim index 5a67f9475..53f230b7b 100755 --- a/compiler/c2nim/clex.nim +++ b/compiler/c2nim/clex.nim @@ -97,7 +97,7 @@ type next*: ref TToken # for C we need arbitrary look-ahead :-( TLexer* = object of TBaseLexer - filename*: string + fileIdx*: int32 inDirective: bool proc getTok*(L: var TLexer, tok: var TToken) @@ -117,7 +117,7 @@ proc fillToken(L: var TToken) = proc openLexer*(lex: var TLexer, filename: string, inputstream: PLLStream) = openBaseLexer(lex, inputstream) - lex.filename = filename + lex.fileIdx = filename.fileInfoIdx proc closeLexer*(lex: var TLexer) = inc(gLinesCompiled, lex.LineNumber) @@ -127,13 +127,13 @@ proc getColumn*(L: TLexer): int = result = getColNumber(L, L.bufPos) proc getLineInfo*(L: TLexer): TLineInfo = - result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) + result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos)) proc lexMessage*(L: TLexer, msg: TMsgKind, arg = "") = msgs.GenericMessage(getLineInfo(L), msg, arg) proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = - var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) + var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart) msgs.GenericMessage(info, msg, arg) proc TokKindToStr*(k: TTokKind): string = diff --git a/compiler/commands.nim b/compiler/commands.nim index bce24c5da..f07361abe 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -459,9 +459,7 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = if strutils.find(switch, '.') >= 0: options.setConfigVar(switch, arg) else: InvalidCmdLineOption(pass, switch, info) -proc ProcessCommand(switch: string, pass: TCmdLinePass) = - var - cmd, arg: string - var info = newLineInfo("command line", 1, 1) - splitSwitch(switch, cmd, arg, pass, info) - ProcessSwitch(cmd, arg, pass, info) +proc ProcessCommand(switch: string, pass: TCmdLinePass) = + var cmd, arg: string + splitSwitch(switch, cmd, arg, pass, gCmdLineInfo) + processSwitch(cmd, arg, pass, gCmdLineInfo) diff --git a/compiler/lexer.nim b/compiler/lexer.nim index 653644f8f..63a9bef87 100755 --- a/compiler/lexer.nim +++ b/compiler/lexer.nim @@ -96,7 +96,7 @@ type # documentation comments are here too TLexer* = object of TBaseLexer - filename*: string + fileIdx*: int32 indentStack*: seq[int] # the indentation stack dedent*: int # counter for DED token generation indentAhead*: int # if > 0 an indendation has already been read @@ -198,7 +198,7 @@ proc fillToken(L: var TToken) = proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) = openBaseLexer(lex, inputstream) lex.indentStack = @[0] - lex.filename = filename + lex.fileIdx = filename.fileInfoIdx lex.indentAhead = - 1 inc(lex.Linenumber, inputstream.lineOffset) @@ -210,13 +210,13 @@ proc getColumn(L: TLexer): int = result = getColNumber(L, L.bufPos) proc getLineInfo(L: TLexer): TLineInfo = - result = newLineInfo(L.filename, L.linenumber, getColNumber(L, L.bufpos)) + result = newLineInfo(L.fileIdx, L.linenumber, getColNumber(L, L.bufpos)) proc lexMessage(L: TLexer, msg: TMsgKind, arg = "") = msgs.Message(getLineInfo(L), msg, arg) proc lexMessagePos(L: var TLexer, msg: TMsgKind, pos: int, arg = "") = - var info = newLineInfo(L.filename, L.linenumber, pos - L.lineStart) + var info = newLineInfo(L.fileIdx, L.linenumber, pos - L.lineStart) msgs.Message(info, msg, arg) proc matchUnderscoreChars(L: var TLexer, tok: var TToken, chars: TCharSet) = diff --git a/compiler/main.nim b/compiler/main.nim index fd2908516..4d65f84bb 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -176,7 +176,7 @@ proc CommandSuggest = proc wantMainModule = if gProjectFull.len == 0: - Fatal(newLineInfo("command line", 1, 1), errCommandExpectsFilename) + Fatal(gCmdLineInfo, errCommandExpectsFilename) proc MainCommand = appendStr(searchPaths, options.libpath) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 3090198ac..32afdee3b 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -8,7 +8,7 @@ # import - options, strutils, os + options, strutils, os, tables type TMsgKind* = enum @@ -384,6 +384,11 @@ const type TNoteKind* = range[warnMin..hintMax] # "notes" are warnings or hints TNoteKinds* = set[TNoteKind] + + TFileInfo*{.final.} = object + fullPath*: string # This is a canonical full filesystem path + projPath*: string # This is relative to the project's root + TLineInfo*{.final.} = object # This is designed to be as small as possible, # because it is used # in syntax nodes. We safe space here by using @@ -395,7 +400,37 @@ type ERecoverableError* = object of EInvalidValue -proc newLineInfo*(filename: string, line, col: int): TLineInfo +var + filenameToIndexTbl = initTable[string, int32]() + fileInfos: seq[TFileInfo] = @[] + +proc newFileInfo(fullPath, projPath: string): TFileInfo = + result.fullPath = fullPath + result.projPath = projPath + +proc fileInfoIdx*(filename: string): int32 = + var canonical = canonicalizePath(filename) + + if filenameToIndexTbl.hasKey(canonical): + result = filenameToIndexTbl[canonical] + else: + result = fileInfos.len.int32 + fileInfos.add(newFileInfo(canonical, canonical.shortenDir)) + filenameToIndexTbl[canonical] = result + +proc newLineInfo*(filename: string, line, col: int): TLineInfo = + result.fileIndex = filename.fileInfoIdx + result.line = int16(line) + result.col = int16(col) + +proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo = + result.fileIndex = fileInfoIdx + result.line = int16(line) + result.col = int16(col) + +fileInfos.add(newFileInfo("command line", "")) +var gCmdLineInfo* = newLineInfo(int32(0), 1, 1) + proc raiseRecoverableError*() {.noinline, noreturn.} = raise newException(ERecoverableError, "") @@ -423,9 +458,7 @@ proc UnknownLineInfo*(): TLineInfo = result.fileIndex = -1 var - filenames: seq[tuple[filename: string, fullpath: string]] = @[] msgContext: seq[TLineInfo] = @[] - gCmdLineInfo* = newLineInfo("command line", -1, -1) proc pushInfoContext*(info: TLineInfo) = msgContext.add(info) @@ -433,31 +466,13 @@ proc pushInfoContext*(info: TLineInfo) = proc popInfoContext*() = setlen(msgContext, len(msgContext) - 1) -proc includeFilename*(f: string): int = - for i in countdown(high(filenames), low(filenames)): - if filenames[i].filename == f: - return i - - result = len(filenames) - - var fullpath: string - try: fullpath = expandFilename(f) - except: fullpath = "" - - filenames.add((filename: f, fullpath: fullpath)) - -proc newLineInfo(filename: string, line, col: int): TLineInfo = - result.fileIndex = includeFilename(filename) - result.line = int16(line) - result.col = int16(col) - -proc ToFilename*(info: TLineInfo): string = +proc ToFilename*(info: TLineInfo): string = if info.fileIndex < 0: result = "???" - else: result = filenames[info.fileIndex].filename + else: result = fileInfos[info.fileIndex].projPath proc toFullPath*(info: TLineInfo): string = if info.fileIndex < 0: result = "???" - else: result = filenames[info.fileIndex].fullpath + else: result = fileInfos[info.fileIndex].fullPath proc ToLinenumber*(info: TLineInfo): int {.inline.} = result = info.line diff --git a/compiler/nimrod.nim b/compiler/nimrod.nim index 6a9ae690e..24dbc0617 100755 --- a/compiler/nimrod.nim +++ b/compiler/nimrod.nim @@ -70,14 +70,14 @@ proc HandleCmdLine() = ProcessCmdLine(passCmd1) if gProjectName != "": try: - gProjectFull = expandFilename(gProjectName) + gProjectFull = canonicalizePath(gProjectName) except EOS: gProjectFull = gProjectName var p = splitFile(gProjectFull) gProjectPath = p.dir gProjectName = p.name else: - gProjectPath = getCurrentDir() + 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 diff --git a/compiler/options.nim b/compiler/options.nim index ea36e3c6a..bf01ea002 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -138,14 +138,15 @@ proc getPrefixDir*(): string = ## gets the application directory result = SplitPath(getAppDir()).head +proc canonicalizePath*(path: string): string = + result = path.expandFilename + when not FileSystemCaseSensitive: result = result.toLower + proc shortenDir*(dir: string): string = ## returns the interesting part of a dir var prefix = getPrefixDir() & dirSep if startsWith(dir, prefix): return substr(dir, len(prefix)) - prefix = getCurrentDir() & dirSep - if startsWith(dir, prefix): - return substr(dir, len(prefix)) prefix = gProjectPath & dirSep if startsWith(dir, prefix): return substr(dir, len(prefix)) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 2dbfa9497..3766841f1 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -796,7 +796,7 @@ proc evalInclude(c: PContext, n: PNode): PNode = addSon(result, n) for i in countup(0, sonsLen(n) - 1): var f = getModuleFile(n.sons[i]) - var fileIndex = includeFilename(f) + var fileIndex = f.fileInfoIdx if ContainsOrIncl(c.includedFiles, fileIndex): GlobalError(n.info, errRecursiveDependencyX, f) addSon(result, semStmt(c, gIncludeFile(f))) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index cd6cbe859..a6bde6e40 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -713,7 +713,7 @@ proc matches*(c: PContext, n: PNode, m: var TCandidate) = when false: if sfSystemModule notin c.module.flags: - if includeFilename("temp.nim") == c.module.info.fileIndex: + if fileInfoIdx("temp.nim") == c.module.info.fileIndex: echo "########################" echo m.call.renderTree for i in 1..m.call.len-1: |