summary refs log tree commit diff stats
path: root/compiler/msgs.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/msgs.nim')
-rw-r--r--compiler/msgs.nim147
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