66pub ( crate ) mod ir;
77mod vm;
88
9+ use std:: borrow:: Cow ;
10+
911use ariadne:: { Color , Label , ReportBuilder } ;
1012pub use ir:: {
1113 Instruction ,
@@ -24,12 +26,15 @@ pub enum InterpreterError {
2426 RecursionDepth ( AriadneSpan ) ,
2527 #[ error( "Indirect call to an undefined function!" ) ]
2628 UnknownIndFunction ( AriadneSpan , String ) ,
29+ #[ error( "Attempted to divide `{}` by zero here!" , quacks_like_a_float( . 1 ) ) ]
30+ DivByZeroAttempted ( AriadneSpan , String ) ,
2731}
2832
2933impl InterpreterError {
3034 pub fn emit_diagnostic ( & self , store : & mut DiagnosticStore ) {
3135 match self {
32- Self :: UnknownIndFunction ( span, _)
36+ Self :: DivByZeroAttempted ( span, _)
37+ | Self :: UnknownIndFunction ( span, _)
3338 | Self :: RecursionDepth ( span)
3439 | Self :: ArityMismatch ( span, _, _)
3540 | Self :: UnknownFunction ( span) => self . add_diagnostic_cached ( store, span. clone ( ) ) ,
@@ -43,7 +48,8 @@ impl Diagnostic for InterpreterError {
4348 }
4449 fn span ( & self ) -> Option < Span > {
4550 match self {
46- Self :: UnknownIndFunction ( ( _, span) , _)
51+ Self :: DivByZeroAttempted ( ( _, span) , _)
52+ | Self :: UnknownIndFunction ( ( _, span) , _)
4753 | Self :: RecursionDepth ( ( _, span) )
4854 | Self :: ArityMismatch ( ( _, span) , _, _)
4955 | Self :: UnknownFunction ( ( _, span) ) => Some ( span. clone ( ) ) ,
@@ -75,10 +81,26 @@ impl Diagnostic for InterpreterError {
7581 Self :: UnknownIndFunction ( _, name) => {
7682 & format ! ( "This code tried to call the unknown function `{name}` indirectly." )
7783 }
84+ Self :: DivByZeroAttempted ( _, _) => {
85+ "Division and modular arithmetic by zero is always fatal in AWK. To avoid this, \
86+ you can use an\n if statement or a ternary expression. You may optionally introduce \
87+ IEEE 754 not-a-number values:\n \
88+ `a / b` --> `(+b != 0) ? (a / b) : +\" +nan\" `.\n Note the importance of the `+` \
89+ operator, which forces values into numbers. Otherwise, some\n values of `b`, like \
90+ an empty string, would still trigger this error. It also parses the \" +nan\" ."
91+ }
7892 } ;
7993 report. set_help ( note) ;
8094 }
8195 fn is_unrecoverable ( & self ) -> bool {
8296 true
8397 }
8498}
99+
100+ fn quacks_like_a_float ( val : & str ) -> Cow < ' _ , str > {
101+ if val. parse :: < f64 > ( ) . is_ok ( ) {
102+ val. into ( )
103+ } else {
104+ format ! ( "{val:?}" ) . into ( )
105+ }
106+ }
0 commit comments