diff options
Diffstat (limited to 'compiler/msgs.nim')
-rw-r--r-- | compiler/msgs.nim | 147 |
1 files changed, 82 insertions, 65 deletions
diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 70504cfc9..5ae2c4970 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -10,21 +10,24 @@ import options, strutils, os, tables, ropes, platform, terminal, macros +const + explanationsBaseUrl* = "https://nim-lang.org/docs/manual" + type TMsgKind* = enum errUnknown, errInternal, errIllFormedAstX, errCannotOpenFile, errGenerated, - errXCompilerDoesNotSupportCpp, errStringLiteralExpected, + errStringLiteralExpected, errIntLiteralExpected, errInvalidCharacterConstant, errClosingTripleQuoteExpected, errClosingQuoteExpected, - errTabulatorsAreNotAllowed, errInvalidToken, errLineTooLong, + errTabulatorsAreNotAllowed, errInvalidToken, errInvalidNumber, errInvalidNumberOctalCode, errNumberOutOfRange, errNnotAllowedInCharacter, errClosingBracketExpected, errMissingFinalQuote, errIdentifierExpected, errNewlineExpected, errInvalidModuleName, - errOperatorExpected, errTokenExpected, errStringAfterIncludeExpected, + errOperatorExpected, errTokenExpected, errRecursiveDependencyX, errOnOrOffExpected, errNoneSpeedOrSizeExpected, errInvalidPragma, errUnknownPragma, errInvalidDirectiveX, errAtPopWithoutPush, errEmptyAsm, errInvalidIndentation, - errExceptionExpected, errExceptionAlreadyHandled, + errExceptionAlreadyHandled, errYieldNotAllowedHere, errYieldNotAllowedInTryStmt, errInvalidNumberOfYieldExpr, errCannotReturnExpr, errNoReturnWithReturnTypeNotAllowed, errAttemptToRedefine, @@ -68,7 +71,7 @@ type errWrongNumberOfArgumentsInCall, errMissingGenericParamsForTemplate, errXCannotBePassedToProcVar, - errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProcX, errImplOfXNotAllowed, + errPragmaOnlyInHeaderOfProcX, errImplOfXNotAllowed, errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX, errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice, errInvalidOrderInArrayConstructor, @@ -87,7 +90,8 @@ type errNoReturnTypeDeclared, errNoCommand, errInvalidCommandX, errXOnlyAtModuleScope, errXNeedsParamObjectType, - errTemplateInstantiationTooNested, errInstantiationFrom, + errTemplateInstantiationTooNested, errMacroInstantiationTooNested, + errInstantiationFrom, errInvalidIndexValueForTuple, errCommandExpectsFilename, errMainModuleMustBeSpecified, errXExpected, @@ -144,7 +148,6 @@ const errIllFormedAstX: "illformed AST: $1", errCannotOpenFile: "cannot open \'$1\'", errGenerated: "$1", - errXCompilerDoesNotSupportCpp: "\'$1\' compiler does not support C++", errStringLiteralExpected: "string literal expected", errIntLiteralExpected: "integer literal expected", errInvalidCharacterConstant: "invalid character constant", @@ -152,7 +155,6 @@ const errClosingQuoteExpected: "closing \" expected", errTabulatorsAreNotAllowed: "tabulators are not allowed", errInvalidToken: "invalid token: $1", - errLineTooLong: "line too long", errInvalidNumber: "$1 is not a valid number", errInvalidNumberOctalCode: "$1 is not a valid number; did you mean octal? Then use one of '0o', '0c' or '0C'.", errNumberOutOfRange: "number $1 out of valid range", @@ -164,7 +166,6 @@ const errInvalidModuleName: "invalid module name: '$1'", errOperatorExpected: "operator expected, but found \'$1\'", errTokenExpected: "\'$1\' expected", - errStringAfterIncludeExpected: "string after \'include\' expected", errRecursiveDependencyX: "recursive dependency: \'$1\'", errOnOrOffExpected: "\'on\' or \'off\' expected", errNoneSpeedOrSizeExpected: "\'none\', \'speed\' or \'size\' expected", @@ -174,7 +175,6 @@ const errAtPopWithoutPush: "\'pop\' without a \'push\' pragma", errEmptyAsm: "empty asm statement", errInvalidIndentation: "invalid indentation", - errExceptionExpected: "exception expected", errExceptionAlreadyHandled: "exception already handled", errYieldNotAllowedHere: "'yield' only allowed in an iterator", errYieldNotAllowedInTryStmt: "'yield' cannot be used within 'try' in a non-inlined iterator", @@ -280,7 +280,6 @@ const errWrongNumberOfArgumentsInCall: "wrong number of arguments in call to '$1'", errMissingGenericParamsForTemplate: "'$1' has unspecified generic parameters", errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar", - errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration", errPragmaOnlyInHeaderOfProcX: "pragmas are only allowed in the header of a proc; redefinition of $1", errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", errImplOfXexpected: "implementation of \'$1\' expected", @@ -329,7 +328,8 @@ const errInvalidCommandX: "invalid command: \'$1\'", errXOnlyAtModuleScope: "\'$1\' is only allowed at top level", errXNeedsParamObjectType: "'$1' needs a parameter that has an object type", - errTemplateInstantiationTooNested: "template/macro instantiation too nested", + errTemplateInstantiationTooNested: "template instantiation too nested, try --evalTemplateLimit:N", + errMacroInstantiationTooNested: "macro instantiation too nested, try --evalMacroLimit:N", errInstantiationFrom: "template/generic instantiation from here", errInvalidIndexValueForTuple: "invalid index value for tuple subscript", errCommandExpectsFilename: "command expects a filename argument", @@ -495,15 +495,18 @@ type # and parsed; usually 'nil' but is used # for 'nimsuggest' hash*: string # the checksum of the file - + when defined(nimpretty): + fullContent*: string + FileIndex* = distinct int32 TLineInfo* = object # This is designed to be as small as possible, # because it is used # in syntax nodes. We save space here by using # two int16 and an int32. # On 64 bit and on 32 bit systems this is # only 8 bytes. - line*, col*: int16 - fileIndex*: int32 + line*: uint16 + col*: int16 + fileIndex*: FileIndex when defined(nimpretty): offsetA*, offsetB*: int commentOffsetA*, commentOffsetB*: int @@ -517,6 +520,8 @@ type ERecoverableError* = object of ValueError ESuggestDone* = object of Exception +proc `==`*(a, b: FileIndex): bool {.borrow.} + const NotesVerbosity*: array[0..3, TNoteKinds] = [ {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit, @@ -541,14 +546,14 @@ const {low(TNoteKind)..high(TNoteKind)}] const - InvalidFileIDX* = int32(-1) + InvalidFileIDX* = FileIndex(-1) var ForeignPackageNotes*: TNoteKinds = {hintProcessing, warnUnknownMagic, hintQuitCalled, hintExecuting} - filenameToIndexTbl = initTable[string, int32]() + filenameToIndexTbl = initTable[string, FileIndex]() fileInfos*: seq[TFileInfo] = @[] - systemFileIdx*: int32 + systemFileIdx*: FileIndex proc toCChar*(c: char): string = case c @@ -583,6 +588,18 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo = result.quotedFullName = fullPath.makeCString if optEmbedOrigSrc in gGlobalOptions or true: result.lines = @[] + when defined(nimpretty): + if result.fullPath.len > 0: + try: + result.fullContent = readFile(result.fullPath) + except IOError: + #rawMessage(errCannotOpenFile, result.fullPath) + # XXX fixme + result.fullContent = "" + +when defined(nimpretty): + proc fileSection*(fid: FileIndex; a, b: int): string = + substr(fileInfos[fid.int].fullContent, a, b) proc fileInfoKnown*(filename: string): bool = var @@ -593,7 +610,7 @@ proc fileInfoKnown*(filename: string): bool = canon = filename result = filenameToIndexTbl.hasKey(canon) -proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 = +proc fileInfoIdx*(filename: string; isKnownFile: var bool): FileIndex = var canon: string pseudoPath = false @@ -611,28 +628,28 @@ proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 = result = filenameToIndexTbl[canon] else: isKnownFile = false - result = fileInfos.len.int32 + result = fileInfos.len.FileIndex fileInfos.add(newFileInfo(canon, if pseudoPath: filename else: canon.shortenDir)) filenameToIndexTbl[canon] = result -proc fileInfoIdx*(filename: string): int32 = +proc fileInfoIdx*(filename: string): FileIndex = var dummy: bool result = fileInfoIdx(filename, dummy) -proc newLineInfo*(fileInfoIdx: int32, line, col: int): TLineInfo = +proc newLineInfo*(fileInfoIdx: FileIndex, line, col: int): TLineInfo = result.fileIndex = fileInfoIdx - result.line = int16(line) + result.line = uint16(line) result.col = int16(col) proc newLineInfo*(filename: string, line, col: int): TLineInfo {.inline.} = result = newLineInfo(filename.fileInfoIdx, line, col) fileInfos.add(newFileInfo("", "command line")) -var gCmdLineInfo* = newLineInfo(int32(0), 1, 1) +var gCmdLineInfo* = newLineInfo(FileIndex(0), 1, 1) fileInfos.add(newFileInfo("", "compilation artifact")) -var gCodegenLineInfo* = newLineInfo(int32(1), 1, 1) +var gCodegenLineInfo* = newLineInfo(FileIndex(1), 1, 1) proc raiseRecoverableError*(msg: string) {.noinline, noreturn.} = raise newException(ERecoverableError, msg) @@ -648,9 +665,9 @@ var gMainPackageNotes*: TNoteKinds = NotesVerbosity[1] proc unknownLineInfo*(): TLineInfo = - result.line = int16(-1) + result.line = uint16(0) result.col = int16(-1) - result.fileIndex = -1 + result.fileIndex = InvalidFileIDX type Severity* {.pure.} = enum ## VS Code only supports these three @@ -712,32 +729,32 @@ proc getInfoContext*(index: int): TLineInfo = if i >=% L: result = unknownLineInfo() else: result = msgContext[i] -template toFilename*(fileIdx: int32): string = - (if fileIdx < 0: "???" else: fileInfos[fileIdx].projPath) +template toFilename*(fileIdx: FileIndex): string = + (if fileIdx.int32 < 0: "???" else: fileInfos[fileIdx.int32].projPath) -proc toFullPath*(fileIdx: int32): string = - if fileIdx < 0: result = "???" - else: result = fileInfos[fileIdx].fullPath +proc toFullPath*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" + else: result = fileInfos[fileIdx.int32].fullPath -proc setDirtyFile*(fileIdx: int32; filename: string) = - assert fileIdx >= 0 - fileInfos[fileIdx].dirtyFile = filename +proc setDirtyFile*(fileIdx: FileIndex; filename: string) = + assert fileIdx.int32 >= 0 + fileInfos[fileIdx.int32].dirtyFile = filename -proc setHash*(fileIdx: int32; hash: string) = - assert fileIdx >= 0 - shallowCopy(fileInfos[fileIdx].hash, hash) +proc setHash*(fileIdx: FileIndex; hash: string) = + assert fileIdx.int32 >= 0 + shallowCopy(fileInfos[fileIdx.int32].hash, hash) -proc getHash*(fileIdx: int32): string = - assert fileIdx >= 0 - shallowCopy(result, fileInfos[fileIdx].hash) +proc getHash*(fileIdx: FileIndex): string = + assert fileIdx.int32 >= 0 + shallowCopy(result, fileInfos[fileIdx.int32].hash) -proc toFullPathConsiderDirty*(fileIdx: int32): string = - if fileIdx < 0: +proc toFullPathConsiderDirty*(fileIdx: FileIndex): string = + if fileIdx.int32 < 0: result = "???" - elif not fileInfos[fileIdx].dirtyFile.isNil: - result = fileInfos[fileIdx].dirtyFile + elif not fileInfos[fileIdx.int32].dirtyFile.isNil: + result = fileInfos[fileIdx.int32].dirtyFile else: - result = fileInfos[fileIdx].fullPath + result = fileInfos[fileIdx.int32].fullPath template toFilename*(info: TLineInfo): string = info.fileIndex.toFilename @@ -746,15 +763,15 @@ template toFullPath*(info: TLineInfo): string = info.fileIndex.toFullPath proc toMsgFilename*(info: TLineInfo): string = - if info.fileIndex < 0: + if info.fileIndex.int32 < 0: result = "???" elif gListFullPaths: - result = fileInfos[info.fileIndex].fullPath + result = fileInfos[info.fileIndex.int32].fullPath else: - result = fileInfos[info.fileIndex].projPath + result = fileInfos[info.fileIndex.int32].projPath proc toLinenumber*(info: TLineInfo): int {.inline.} = - result = info.line + result = int info.line proc toColumn*(info: TLineInfo): int {.inline.} = result = info.col @@ -771,7 +788,7 @@ proc `??`* (info: TLineInfo, filename: string): bool = # only for debugging purposes result = filename in info.toFilename -const trackPosInvalidFileIdx* = -2 # special marker so that no suggestions +const trackPosInvalidFileIdx* = FileIndex(-2) # special marker so that no suggestions # are produced within comments and string literals var gTrackPos*: TLineInfo var gTrackPosAttached*: bool ## whether the tracking position was attached to some @@ -910,7 +927,7 @@ proc writeContext(lastinfo: TLineInfo) = else: styledMsgWriteln(styleBright, PosFormat % [toMsgFilename(msgContext[i]), - coordToStr(msgContext[i].line), + coordToStr(msgContext[i].line.int), coordToStr(msgContext[i].col+1)], resetStyle, getMessageStr(errInstantiationFrom, "")) @@ -978,7 +995,7 @@ proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string = of warnMin..warnMax: WarningTitle of hintMin..hintMax: HintTitle else: ErrorTitle - result = PosFormat % [toMsgFilename(info), coordToStr(info.line), + result = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] & title & getMessageStr(msg, arg) @@ -1019,7 +1036,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, # NOTE: currently line info line numbers start with 1, # but column numbers start with 0, however most editors expect # first column to be 1, so we need to +1 here - let x = PosFormat % [toMsgFilename(info), coordToStr(info.line), + let x = PosFormat % [toMsgFilename(info), coordToStr(info.line.int), coordToStr(info.col+1)] let s = getMessageStr(msg, arg) @@ -1032,7 +1049,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, KindColor, `%`(KindFormat, kind)) else: styledMsgWriteln(styleBright, x, resetStyle, color, title, resetStyle, s) - if msg in errMin..errMax and hintSource in gNotes: + if hintSource in gNotes: info.writeSurroundingSrc handleError(msg, eh, s) @@ -1077,30 +1094,30 @@ template assertNotNil*(e): untyped = template internalAssert*(e: bool) = if not e: internalError($instantiationInfo()) -proc addSourceLine*(fileIdx: int32, line: string) = - fileInfos[fileIdx].lines.add line.rope +proc addSourceLine*(fileIdx: FileIndex, line: string) = + fileInfos[fileIdx.int32].lines.add line.rope proc sourceLine*(i: TLineInfo): Rope = - if i.fileIndex < 0: return nil + if i.fileIndex.int32 < 0: return nil - if not optPreserveOrigSource and fileInfos[i.fileIndex].lines.len == 0: + if not optPreserveOrigSource and fileInfos[i.fileIndex.int32].lines.len == 0: try: for line in lines(i.toFullPath): addSourceLine i.fileIndex, line.string except IOError: discard - internalAssert i.fileIndex < fileInfos.len + internalAssert i.fileIndex.int32 < fileInfos.len # can happen if the error points to EOF: - if i.line > fileInfos[i.fileIndex].lines.len: return nil + if i.line.int > fileInfos[i.fileIndex.int32].lines.len: return nil - result = fileInfos[i.fileIndex].lines[i.line-1] + result = fileInfos[i.fileIndex.int32].lines[i.line.int-1] proc quotedFilename*(i: TLineInfo): Rope = - internalAssert i.fileIndex >= 0 + internalAssert i.fileIndex.int32 >= 0 if optExcessiveStackTrace in gGlobalOptions: - result = fileInfos[i.fileIndex].quotedFullName + result = fileInfos[i.fileIndex.int32].quotedFullName else: - result = fileInfos[i.fileIndex].quotedName + result = fileInfos[i.fileIndex.int32].quotedName ropes.errorHandler = proc (err: RopesError, msg: string, useWarning: bool) = case err |