summary refs log tree commit diff stats
path: root/nim/msgs.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/msgs.pas')
-rw-r--r--nim/msgs.pas708
1 files changed, 360 insertions, 348 deletions
diff --git a/nim/msgs.pas b/nim/msgs.pas
index 8112b8df7..d65a5a1e4 100644
--- a/nim/msgs.pas
+++ b/nim/msgs.pas
@@ -1,53 +1,54 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-unit msgs;
-
-interface
-
-{$include 'config.inc'}
-
-uses
-  nsystem, options, strutils, nos;
-
-//[[[cog
-//enum = "type\n  TMsgKind = (\n"
-//msgs = "const\n  MsgKindToStr: array [TMsgKind] of string = (\n"
-//warns = "const\n  WarningsToStr: array [0..%d] of string = (\n"
-//hints = "const\n  HintsToStr: array [0..%d] of string = (\n"
-//w = 0 # counts the warnings
-//h = 0 # counts the hints
-//
-//for elem in eval(file('data/messages.yml').read()):
-//  for key, val in elem.iteritems():
-//    enum += '    %s,\n' % key
-//    v = val.replace("'", "''")
-//    if key.startswith('warn'):
-//      msgs +=  "    '%s [%s]',\n" % (v, key[4:])
-//      warns += "    '%s',\n" % key[4:]
-//      w += 1
-//    elif key.startswith('hint'):
-//      msgs +=  "    '%s [%s]',\n" % (v, key[4:])
-//      hints += "    '%s',\n" % key[4:]
-//      h += 1
-//    else:
-//      msgs +=  "    '%s',\n" % v
-//
-//enum = enum[:-2] + ');\n\n'
-//msgs = msgs[:-2] + '\n  );\n'
-//warns = (warns[:-2] + '\n  );\n') % (w-1)
-//hints = (hints[:-2] + '\n  );\n') % (h-1)
-//
-//cog.out(enum)
-//cog.out(msgs)
-//cog.out(warns)
-//cog.out(hints)
-//]]]
+//

+//

+//           The Nimrod Compiler

+//        (c) Copyright 2008 Andreas Rumpf

+//

+//    See the file "copying.txt", included in this

+//    distribution, for details about the copyright.

+//

+unit msgs;

+

+interface

+

+{$include 'config.inc'}

+

+uses

+  nsystem, options, strutils, nos;

+

+//[[[cog

+//from string import replace

+//enum = "type\n  TMsgKind = (\n"

+//msgs = "const\n  MsgKindToStr: array [TMsgKind] of string = (\n"

+//warns = "const\n  WarningsToStr: array [0..%d] of string = (\n"

+//hints = "const\n  HintsToStr: array [0..%d] of string = (\n"

+//w = 0 # counts the warnings

+//h = 0 # counts the hints

+//

+//for elem in eval(open('data/messages.yml').read()):

+//  for key, val in elem.items():

+//    enum = enum + '    %s,\n' % key

+//    v = replace(val, "'", "''")

+//    if key[0:4] == 'warn':

+//      msgs = msgs +  "    '%s [%s]',\n" % (v, key[4:])

+//      warns = warns + "    '%s',\n" % key[4:]

+//      w = w + 1

+//    elif key[0:4] == 'hint':

+//      msgs = msgs + "    '%s [%s]',\n" % (v, key[4:])

+//      hints = hints + "    '%s',\n" % key[4:]

+//      h = h + 1

+//    else:

+//      msgs = msgs + "    '%s',\n" % v

+//

+//enum = enum[:-2] + ');\n\n'

+//msgs = msgs[:-2] + '\n  );\n'

+//warns = (warns[:-2] + '\n  );\n') % (w-1)

+//hints = (hints[:-2] + '\n  );\n') % (h-1)

+//

+//cog.out(enum)

+//cog.out(msgs)

+//cog.out(warns)

+//cog.out(hints)

+//]]]

 type
   TMsgKind = (
     errUnknown,
@@ -293,16 +294,17 @@ type
     warnCommentXIgnored,
     warnUser,
     hintSuccess,
+    hintSuccessX,
     hintLineTooLong,
     hintXDeclaredButNotUsed,
     hintConvToBaseNotNeeded,
     hintConvFromXtoItselfNotNeeded,
     hintExprAlwaysX,
-    hintMo2FileInvalid,
-    hintModuleHasChanged,
-    hintCannotOpenMo2File,
     hintQuitCalled,
     hintProcessing,
+    hintCodeBegin,
+    hintCodeEnd,
+    hintConf,
     hintUser);
 
 const
@@ -439,7 +441,7 @@ const
     'computing the type''s size produced an overflow',
     'set is too large',
     'base type of a set must be an ordinal',
-    'inheritance only works non-final objects',
+    'inheritance only works with non-final objects',
     'inheritance only works with an enum',
     'illegal recursion in type ''$1''',
     'cannot instantiate: ''$1''',
@@ -550,16 +552,17 @@ const
     'comment ''$1'' ignored [CommentXIgnored]',
     '$1 [User]',
     'operation successful [Success]',
+    'operation successful ($1 lines compiled; $2 sec total) [SuccessX]',
     'line too long [LineTooLong]',
     '''$1'' is declared but not used [XDeclaredButNotUsed]',
     'conversion to base object is not needed [ConvToBaseNotNeeded]',
     'conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]',
     'expression evaluates always to ''$1'' [ExprAlwaysX]',
-    'mo2 file ''$1'' is invalid [Mo2FileInvalid]',
-    'module ''$1'' has been changed [ModuleHasChanged]',
-    'mo2 file ''$1'' does not exist [CannotOpenMo2File]',
     'quit() called [QuitCalled]',
-    'processing [Processing]',
+    'processing $1 [Processing]',
+    'generated code listing: [CodeBegin]',
+    'end of listing [CodeEnd]',
+    'used config file ''$1'' [Conf]',
     '$1 [User]'
   );
 const
@@ -580,261 +583,265 @@ const
     'User'
   );
 const
-  HintsToStr: array [0..11] of string = (
+  HintsToStr: array [0..12] of string = (
     'Success',
+    'SuccessX',
     'LineTooLong',
     'XDeclaredButNotUsed',
     'ConvToBaseNotNeeded',
     'ConvFromXtoItselfNotNeeded',
     'ExprAlwaysX',
-    'Mo2FileInvalid',
-    'ModuleHasChanged',
-    'CannotOpenMo2File',
     'QuitCalled',
     'Processing',
+    'CodeBegin',
+    'CodeEnd',
+    'Conf',
     'User'
   );
-//[[[end]]]
-
-const
-  fatalMin = errUnknown;
-  fatalMax = errInternal;
-  errMin = errUnknown;
-  errMax = errUser;
-  warnMin = warnCannotOpenFile;
-  warnMax = pred(hintSuccess);
-  hintMin = hintSuccess;
-  hintMax = high(TMsgKind);
-
-type
-  TNoteKind = warnMin..hintMax;
-  // "notes" are warnings or hints
-  TNoteKinds = set of TNoteKind;
-
-  TLineInfo = record
-    // This is designed to be as small as possible, because it is used
-    // in syntax nodes. We safe 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;
-  end;
-
-function UnknownLineInfo(): TLineInfo;
-
-var
-  gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)];
-  gErrorCounter: int = 0; // counts the number of errors
-  gHintCounter: int = 0;
-  gWarnCounter: int = 0;
-  gErrorMax: int = 1; // stop after gErrorMax errors
-
-const // this format is understood by many text editors: it is the same that
-  // Borland and Freepascal use
-  PosErrorFormat = '$1($2, $3) Error: $4';
-  PosWarningFormat = '$1($2, $3) Warning: $4';
-  PosHintFormat = '$1($2, $3) Hint: $4';
-
-  RawErrorFormat = 'Error: $1';
-  RawWarningFormat = 'Warning: $1';
-  RawHintFormat = 'Hint: $1';
-
-procedure MessageOut(const s: string);
-
-procedure rawMessage(const msg: TMsgKind; const arg: string = '');
-procedure liMessage(const info: TLineInfo; const msg: TMsgKind;
-                    const arg: string = '');
-
-procedure InternalError(const info: TLineInfo; const errMsg: string);
-  overload;
-procedure InternalError(const errMsg: string); overload;
-
-function newLineInfo(const filename: string; line, col: int): TLineInfo;
-
-function ToFilename(const info: TLineInfo): string;
-function toColumn(const info: TLineInfo): int;
-function ToLinenumber(const info: TLineInfo): int;
-
-function MsgKindToString(kind: TMsgKind): string;
-
-// checkpoints are used for debugging:
-function checkpoint(const info: TLineInfo; const filename: string;
-                    line: int): boolean;
-
-procedure addCheckpoint(const info: TLineInfo); overload;
-procedure addCheckpoint(const filename: string; line: int); overload;
-function inCheckpoint(const current: TLineInfo): boolean;
-// prints the line information if in checkpoint
-
-procedure pushInfoContext(const info: TLineInfo);
-procedure popInfoContext;
-
-implementation
-
-function UnknownLineInfo(): TLineInfo;
-begin
-  result.line := -1;
-  result.col := -1;
-  result.fileIndex := -1;
-end;
-
-{@ignore}
-var
-  filenames: array of string;
-  msgContext: array of TLineInfo;
-{@emit
-var
-  filenames: array of string = [];
-  msgContext: array of TLineInfo = [];
-}
-
-procedure pushInfoContext(const info: TLineInfo);
-var
-  len: int;
-begin
-  len := length(msgContext);
-  setLength(msgContext, len+1);
-  msgContext[len] := info;
-end;
-
-procedure popInfoContext;
-begin
-  setLength(msgContext, length(msgContext)-1);
-end;
-
-function includeFilename(const f: string): int;
-var
-  i: int;
-begin
-  for i := high(filenames) downto low(filenames) do
-    if filenames[i] = f then begin
-      result := i; exit
-    end;
-  // not found, so add it:
-  result := length(filenames);
-  setLength(filenames, result+1);
-  filenames[result] := f;
-end;
-
-function checkpoint(const info: TLineInfo; const filename: string;
-                    line: int): boolean;
-begin
-  result := (info.line = line) and (
-    ChangeFileExt(extractFilename(filenames[info.fileIndex]), '') = filename);
-end;
-
-
-{@ignore}
-var
-  checkPoints: array of TLineInfo;
-{@emit
-var
-  checkPoints: array of TLineInfo = [];
-}
-
-procedure addCheckpoint(const info: TLineInfo); overload;
-var
-  len: int;
-begin
-  len := length(checkPoints);
-  setLength(checkPoints, len+1);
-  checkPoints[len] := info;
-end;
-
-procedure addCheckpoint(const filename: string; line: int); overload;
-begin
-  addCheckpoint(newLineInfo(filename, line, -1));
-end;
-
-function newLineInfo(const filename: string; line, col: int): TLineInfo;
-begin
-  result.fileIndex := includeFilename(filename);
-  result.line := int16(line);
-  result.col := int16(col);
-end;
-
-function ToFilename(const info: TLineInfo): string;
-begin
-  if info.fileIndex = -1 then result := '???'
-  else result := filenames[info.fileIndex]
-end;
-
-function ToLinenumber(const info: TLineInfo): int;
-begin
-  result := info.line
-end;
-
-function toColumn(const info: TLineInfo): int;
-begin
-  result := info.col
-end;
-
-procedure MessageOut(const s: string);
-begin  // change only this proc to put it elsewhere
-  Writeln(output, s);
-end;
-
-function coordToStr(const coord: int): string;
-begin
-  if coord = -1 then result := '???'
-  else result := toString(coord)
-end;
-
-function MsgKindToString(kind: TMsgKind): string;
-begin // later versions may provide translated error messages
-  result := msgKindToStr[kind];
-end;
-
-function getMessageStr(msg: TMsgKind; const arg: string): string;
-begin
-  result := format(msgKindToString(msg), [arg]);
-end;
-
-function inCheckpoint(const current: TLineInfo): boolean;
-var
-  i: int;
-begin
-  result := false;
-  if not (optCheckpoints in gOptions) then exit; // ignore all checkpoints
-  for i := 0 to high(checkPoints) do begin
-    if (current.line = int(checkPoints[i].line)) and
-       (current.fileIndex = int(checkPoints[i].fileIndex)) then begin
-      MessageOut(Format('$1($2, $3) Checkpoint: ', [toFilename(current),
-                           coordToStr(current.line),
-                           coordToStr(current.col)]));
-      result := true;
-      exit
-    end
-  end
-end;
-
-procedure handleError(const msg: TMsgKind);
-begin
-  if (msg >= fatalMin) and (msg <= fatalMax) then begin
-    if optVerbose in gGlobalOptions then assert(false);
-    halt(1)
-  end;
-  if (msg >= errMin) and (msg <= errMax) then begin
-    inc(gErrorCounter);
-    if gErrorCounter >= gErrorMax then begin
-      if optVerbose in gGlobalOptions then assert(false);
-      halt(1) // one error stops the compiler
-    end
-  end
-end;
-
-procedure writeContext;
-var
-  i: int;
-begin
-  for i := 0 to length(msgContext)-1 do begin
-    MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]),
-                             coordToStr(msgContext[i].line),
-                             coordToStr(msgContext[i].col),
-                             getMessageStr(errInstantiationFrom, '')]));
-  end;
-end;
-
-procedure rawMessage(const msg: TMsgKind; const arg: string = '');
+//[[[end]]]

+

+const

+  fatalMin = errUnknown;

+  fatalMax = errInternal;

+  errMin = errUnknown;

+  errMax = errUser;

+  warnMin = warnCannotOpenFile;

+  warnMax = pred(hintSuccess);

+  hintMin = hintSuccess;

+  hintMax = high(TMsgKind);

+

+type

+  TNoteKind = warnMin..hintMax;

+  // "notes" are warnings or hints

+  TNoteKinds = set of TNoteKind;

+

+  TLineInfo = record

+    // This is designed to be as small as possible, because it is used

+    // in syntax nodes. We safe 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;

+  end;

+

+function UnknownLineInfo(): TLineInfo;

+

+var

+  gNotes: TNoteKinds = [low(TNoteKind)..high(TNoteKind)];

+  gErrorCounter: int = 0; // counts the number of errors

+  gHintCounter: int = 0;

+  gWarnCounter: int = 0;

+  gErrorMax: int = 1; // stop after gErrorMax errors

+

+const // this format is understood by many text editors: it is the same that

+  // Borland and Freepascal use

+  PosErrorFormat = '$1($2, $3) Error: $4';

+  PosWarningFormat = '$1($2, $3) Warning: $4';

+  PosHintFormat = '$1($2, $3) Hint: $4';

+

+  RawErrorFormat = 'Error: $1';

+  RawWarningFormat = 'Warning: $1';

+  RawHintFormat = 'Hint: $1';

+

+procedure MessageOut(const s: string);

+

+procedure rawMessage(const msg: TMsgKind; const arg: string = ''); overload;

+procedure rawMessage(const msg: TMsgKind; const args: array of string); overload;
+
+procedure liMessage(const info: TLineInfo; const msg: TMsgKind;

+                    const arg: string = '');

+

+procedure InternalError(const info: TLineInfo; const errMsg: string);

+  overload;

+procedure InternalError(const errMsg: string); overload;

+

+function newLineInfo(const filename: string; line, col: int): TLineInfo;

+

+function ToFilename(const info: TLineInfo): string;

+function toColumn(const info: TLineInfo): int;

+function ToLinenumber(const info: TLineInfo): int;

+

+function MsgKindToString(kind: TMsgKind): string;

+

+// checkpoints are used for debugging:

+function checkpoint(const info: TLineInfo; const filename: string;

+                    line: int): boolean;

+

+procedure addCheckpoint(const info: TLineInfo); overload;

+procedure addCheckpoint(const filename: string; line: int); overload;

+function inCheckpoint(const current: TLineInfo): boolean;

+// prints the line information if in checkpoint

+

+procedure pushInfoContext(const info: TLineInfo);

+procedure popInfoContext;

+

+implementation

+

+function UnknownLineInfo(): TLineInfo;

+begin

+  result.line := int16(-1);

+  result.col := int16(-1);

+  result.fileIndex := -1;

+end;

+

+{@ignore}

+var

+  filenames: array of string;

+  msgContext: array of TLineInfo;

+{@emit

+var

+  filenames: array of string = @[];

+  msgContext: array of TLineInfo = @[];

+}

+

+procedure pushInfoContext(const info: TLineInfo);

+var

+  len: int;

+begin

+  len := length(msgContext);

+  setLength(msgContext, len+1);

+  msgContext[len] := info;

+end;

+

+procedure popInfoContext;

+begin

+  setLength(msgContext, length(msgContext)-1);

+end;

+

+function includeFilename(const f: string): int;

+var

+  i: int;

+begin

+  for i := high(filenames) downto low(filenames) do

+    if filenames[i] = f then begin

+      result := i; exit

+    end;

+  // not found, so add it:

+  result := length(filenames);

+  setLength(filenames, result+1);

+  filenames[result] := f;

+end;

+

+function checkpoint(const info: TLineInfo; const filename: string;

+                    line: int): boolean;

+begin

+  result := (int(info.line) = line) and (

+    ChangeFileExt(extractFilename(filenames[info.fileIndex]), '') = filename);

+end;

+

+

+{@ignore}

+var

+  checkPoints: array of TLineInfo;

+{@emit

+var

+  checkPoints: array of TLineInfo = @[];

+}

+

+procedure addCheckpoint(const info: TLineInfo); overload;

+var

+  len: int;

+begin

+  len := length(checkPoints);

+  setLength(checkPoints, len+1);

+  checkPoints[len] := info;

+end;

+

+procedure addCheckpoint(const filename: string; line: int); overload;

+begin

+  addCheckpoint(newLineInfo(filename, line, -1));

+end;

+

+function newLineInfo(const filename: string; line, col: int): TLineInfo;

+begin

+  result.fileIndex := includeFilename(filename);

+  result.line := int16(line);

+  result.col := int16(col);

+end;

+

+function ToFilename(const info: TLineInfo): string;

+begin

+  if info.fileIndex = -1 then result := '???'

+  else result := filenames[info.fileIndex]

+end;

+

+function ToLinenumber(const info: TLineInfo): int;

+begin

+  result := info.line

+end;

+

+function toColumn(const info: TLineInfo): int;

+begin

+  result := info.col

+end;

+

+procedure MessageOut(const s: string);

+begin  // change only this proc to put it elsewhere

+  Writeln(output, s);

+end;

+

+function coordToStr(const coord: int): string;

+begin

+  if coord = -1 then result := '???'

+  else result := toString(coord)

+end;

+

+function MsgKindToString(kind: TMsgKind): string;

+begin // later versions may provide translated error messages

+  result := msgKindToStr[kind];

+end;

+

+function getMessageStr(msg: TMsgKind; const arg: string): string;

+begin

+  result := format(msgKindToString(msg), [arg]);

+end;

+

+function inCheckpoint(const current: TLineInfo): boolean;

+var

+  i: int;

+begin

+  result := false;

+  if not (optCheckpoints in gOptions) then exit; // ignore all checkpoints

+  for i := 0 to high(checkPoints) do begin

+    if (current.line = checkPoints[i].line) and

+       (current.fileIndex = (checkPoints[i].fileIndex)) then begin

+      MessageOut(Format('$1($2, $3) Checkpoint: ', [toFilename(current),

+                           coordToStr(current.line),

+                           coordToStr(current.col)]));

+      result := true;

+      exit

+    end

+  end

+end;

+

+procedure handleError(const msg: TMsgKind);

+begin

+  if msg = errInternal then assert(false); // we want a stack trace here

+  if (msg >= fatalMin) and (msg <= fatalMax) then begin

+    if gVerbosity >= 3 then assert(false);

+    halt(1)

+  end;

+  if (msg >= errMin) and (msg <= errMax) then begin

+    inc(gErrorCounter);

+    if gErrorCounter >= gErrorMax then begin

+      if gVerbosity >= 3 then assert(false);

+      halt(1) // one error stops the compiler

+    end

+  end

+end;

+

+procedure writeContext;

+var

+  i: int;

+begin

+  for i := 0 to length(msgContext)-1 do begin

+    MessageOut(Format(posErrorFormat, [toFilename(msgContext[i]),

+                             coordToStr(msgContext[i].line),

+                             coordToStr(msgContext[i].col),

+                             getMessageStr(errInstantiationFrom, '')]));

+  end;

+end;

+
+procedure rawMessage(const msg: TMsgKind; const args: array of string);
 var
   frmt: string;
 begin
@@ -857,51 +864,56 @@ begin
     end;
     else assert(false) // cannot happen
   end;
-  MessageOut(Format(frmt, [getMessageStr(msg, arg)]));
-  handleError(msg);
-end;
-
-procedure liMessage(const info: TLineInfo; const msg: TMsgKind;
-                    const arg: string = '');
-var
-  frmt: string;
-begin
-  case msg of
-    errMin..errMax: begin
-      writeContext();
-      frmt := posErrorFormat;
-    end;
-    warnMin..warnMax: begin
-      if not (optWarns in gOptions) then exit;
-      if not (msg in gNotes) then exit;
-      frmt := posWarningFormat;
-      inc(gWarnCounter);
-    end;
-    hintMin..hintMax: begin
-      if not (optHints in gOptions) then exit;
-      if not (msg in gNotes) then exit;
-      frmt := posHintFormat;
-      inc(gHintCounter);
-    end;
-    else assert(false) // cannot happen
-  end;
-  MessageOut(Format(frmt, [toFilename(info),
-                           coordToStr(info.line),
-                           coordToStr(info.col),
-                           getMessageStr(msg, arg)]));
+  MessageOut(Format(frmt, format(msgKindToString(msg), args)));
   handleError(msg);
 end;
-
-procedure InternalError(const info: TLineInfo; const errMsg: string);
+

+procedure rawMessage(const msg: TMsgKind; const arg: string = '');

 begin
-  writeContext();
-  liMessage(info, errInternal, errMsg);
-end;
-
-procedure InternalError(const errMsg: string); overload;
-begin
-  writeContext();
-  rawMessage(errInternal, errMsg);
-end;
-
-end.
+  rawMessage(msg, [arg]);
+end;

+

+procedure liMessage(const info: TLineInfo; const msg: TMsgKind;

+                    const arg: string = '');

+var

+  frmt: string;

+begin

+  case msg of

+    errMin..errMax: begin

+      writeContext();

+      frmt := posErrorFormat;

+    end;

+    warnMin..warnMax: begin

+      if not (optWarns in gOptions) then exit;

+      if not (msg in gNotes) then exit;

+      frmt := posWarningFormat;

+      inc(gWarnCounter);

+    end;

+    hintMin..hintMax: begin

+      if not (optHints in gOptions) then exit;

+      if not (msg in gNotes) then exit;

+      frmt := posHintFormat;

+      inc(gHintCounter);

+    end;

+    else assert(false) // cannot happen

+  end;

+  MessageOut(Format(frmt, [toFilename(info),

+                           coordToStr(info.line),

+                           coordToStr(info.col),

+                           getMessageStr(msg, arg)]));

+  handleError(msg);

+end;

+

+procedure InternalError(const info: TLineInfo; const errMsg: string);

+begin

+  writeContext();

+  liMessage(info, errInternal, errMsg);

+end;

+

+procedure InternalError(const errMsg: string); overload;

+begin

+  writeContext();

+  rawMessage(errInternal, errMsg);

+end;

+

+end.