@@ -609,7 +609,6 @@ proc report*(conf: ConfigRef, node: PNode): TErrorHandling =
609609
610610proc fillReportAndHandleVmTrace (c: ConfigRef , r: var Report ,
611611 reportFrom: InstantiationInfo ) =
612- r.reportFrom = toReportLineInfo (reportFrom)
613612 if r.category in { repSem, repVM } and r.location.isSome ():
614613 r.context = c.getContext (r.location.get ())
615614
@@ -621,24 +620,63 @@ proc handleReport*(
621620 r: Report ,
622621 reportFrom: InstantiationInfo ,
623622 eh: TErrorHandling = doNothing) {.noinline .} =
623+ # # Takes the report `r` and handles it. If the report is "enabled" according
624+ # # to the active configuration, it is passed to the active report hook and,
625+ # # if the report corresponds to an error, error handling is performed.
626+ # # `eh` is currently only a suggestion, and it is sometimes ignored depending
627+ # # on the currently active configuration.
624628 var rep = r
625- fillReportAndHandleVmTrace (conf, rep, reportFrom)
629+ rep.reportFrom = toReportLineInfo (reportFrom)
630+
631+ if not conf.isEnabled (rep):
632+ # the report is disabled -> neither invoke the report hook nor perform
633+ # error handling
634+ return
635+
636+ var userAction = doNothing
637+ case writabilityKind (conf, rep)
638+ of writeDisabled:
639+ discard " don't invoke the hook"
640+ of writeEnabled:
641+ # go through the report hook
642+ fillReportAndHandleVmTrace (conf, rep, reportFrom)
643+ userAction = conf.report (rep)
644+ of writeForceEnabled:
645+ # also go through the report hook, but temporarily override ``writeln``
646+ # with something that always echoes something
647+ fillReportAndHandleVmTrace (conf, rep, reportFrom)
648+ let oldHook = conf.writelnHook
649+ conf.writelnHook = proc (conf: ConfigRef , msg: string , flags: MsgFlags ) =
650+ echo msg
626651
627- let
628652 userAction = conf.report (rep)
629- (action, trace) =
630- case userAction
631- of doDefault:
632- errorActions (conf, rep, eh)
633- else :
634- (userAction, false )
653+ conf.writelnHook = oldHook
635654
655+ # ``errorActions`` also increments the error counter, so make sure to always
656+ # call it
657+ var (action, trace) = errorActions (conf, rep, eh)
658+
659+ # decide what to do, based on the hook-provided action and the computed
660+ # action. The more severe handling out of the two wins
661+ case userAction
662+ of doAbort:
663+ # a hook-requested abort always overrides the computed handling
664+ (action, trace) = (doAbort, false )
665+ of doRaise:
666+ case action
667+ of doRaise, doAbort:
668+ discard " a hook-requested raise doesn't override an abort"
669+ of doNothing, doDefault:
670+ (action, trace) = (doRaise, false )
671+ of doNothing, doDefault:
672+ discard " use the computed strategy"
673+
674+ # now perform the selected action:
636675 case action
637676 of doAbort: quit (conf, trace)
638677 of doRaise: raiseRecoverableError (" report" )
639678 of doNothing: discard
640- of doDefault: assert (
641- false ,
679+ of doDefault: unreachable (
642680 " Default error handing action must be turned into ignore/raise/abort" )
643681
644682template globalAssert * (
@@ -665,34 +703,6 @@ template globalReport*(conf: ConfigRef, report: ReportTypes) =
665703 handleReport (
666704 conf, wrap (report, instLoc ()), instLoc (), doRaise)
667705
668- proc reportAndFail * (
669- conf: ConfigRef , r: Report , reportFrom: InstantiationInfo ) =
670- # # Similar to `handleReport`, but, unless overridden with aborting
671- # # (`doAbort`) by the structured report hook, always raises a recoverable
672- # # error.
673- var rep = r
674- fillReportAndHandleVmTrace (conf, rep, reportFrom)
675-
676- case conf.report (rep)
677- of doAbort:
678- quit (conf, false )
679- of doDefault:
680- let (action, trace) = errorActions (conf, rep, doRaise)
681- case action
682- of doAbort:
683- quit (conf, trace)
684- of doRaise, doNothing:
685- raiseRecoverableError (" report" )
686- of doDefault:
687- unreachable ()
688- of doRaise, doNothing:
689- raiseRecoverableError (" report" )
690-
691- template reportAndFail * (
692- conf: ConfigRef ; info: TLineInfo , report: ReportTypes ) =
693- reportAndFail (
694- conf, wrap (report, instLoc (), info), instLoc ())
695-
696706template localReport * (conf: ConfigRef ; info: TLineInfo , report: ReportTypes ) =
697707 {.line .}:
698708 handleReport (
@@ -717,27 +727,9 @@ template localReport*(conf: ConfigRef, report: Report) =
717727
718728# xxx: `internalError` and `internalAssert` in conjunction with `handleReport`,
719729# and the whole concept of "reports" indicating error handling action at a
720- # callsite, is *terrible*. Since neither will necessarily raise/end
721- # execution of the current routine, which may lead to NPEs and the like.
722-
723- template internalError * (
724- conf: ConfigRef , repKind: InternalReportKind , fail: string ): untyped =
725- # # Causes an internal error; but does not necessarily raise/end the currently
726- # # executing routine.
727- conf.handleReport (
728- wrap (InternalReport (kind: repKind, msg: fail), instLoc ()),
729- instLoc (),
730- doAbort)
731-
732- template internalError * (
733- conf: ConfigRef , info: TLineInfo ,
734- repKind: InternalReportKind , fail: string ): untyped =
735- # # Causes an internal error; but does not necessarily raise/end the currently
736- # # executing routine.
737- conf.handleReport (
738- wrap (InternalReport (kind: repKind, msg: fail), instLoc (), info),
739- instLoc (),
740- doAbort)
730+ # callsite, is *terrible*. While it will result in the compiler exiting,
731+ # it is currently implemented very indirectly, through
732+ # ``isCompilerFatal``.
741733
742734proc doInternalUnreachable * (conf: ConfigRef , info: TLineInfo , msg: string ,
743735 instLoc: InstantiationInfo ) {.noreturn , inline .} =
@@ -752,19 +744,18 @@ proc doInternalUnreachable*(conf: ConfigRef, info: TLineInfo, msg: string,
752744 wrap (intRep, instLoc, info)
753745
754746 conf.handleReport (rep, instLoc, doAbort)
747+ unreachable (" not aborted" )
755748
756749template internalError * (
757750 conf: ConfigRef ,
758751 info: TLineInfo ,
759752 fail: string ,
760753 ): untyped =
761- # # Causes an internal error; but does not necessarily raise/end the currently
762- # # executing routine.
754+ # # Causes an internal error. Always ends the currently executing routine.
763755 doInternalUnreachable (conf, info, fail, instLoc ())
764756
765757template internalError * (conf: ConfigRef , fail: string ): untyped =
766- # # Causes an internal error; but does not necessarily raise/end the currently
767- # # executing routine.
758+ # # Causes an internal error. Always ends the currently executing routine.
768759 doInternalUnreachable (conf, unknownLineInfo, fail, instLoc ())
769760
770761proc doInternalAssert * (conf: ConfigRef ,
@@ -782,17 +773,18 @@ proc doInternalAssert*(conf: ConfigRef,
782773 wrap (intRep, instLoc, info)
783774
784775 conf.handleReport (rep, instLoc, doAbort)
776+ unreachable (" not aborted" )
785777
786778template internalAssert * (
787779 conf: ConfigRef , condition: bool , info: TLineInfo , failMsg: string = " " ) =
788- # # Causes an internal error if the provided condition evaluates to false; but
789- # # does not necessarily raise/end the currently executing routine.
780+ # # Causes an internal error if the provided condition evaluates to false.
781+ # # Always ends the currently executing routine.
790782 if not condition:
791783 doInternalAssert (conf, instLoc (), failMsg, info)
792784
793785template internalAssert * (conf: ConfigRef , condition: bool , failMsg = " " ) =
794- # # Causes an internal error if the provided condition evaluates to false; but
795- # # does not necessarily raise/end the currently executing routine.
786+ # # Causes an internal error if the provided condition evaluates to false.
787+ # # Always ends the currently executing routine.
796788 if not condition:
797789 doInternalAssert (conf, instLoc (), failMsg)
798790
0 commit comments