@@ -877,25 +877,65 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
877
877
}
878
878
879
879
fn infer_negate_bool ( & mut self , location : SrcSpan , value : UntypedExpr ) -> TypedExpr {
880
- let value = self . infer ( value) ;
880
+ self . infer_multiple_negate_bool ( location, 1 , location, value)
881
+ }
881
882
883
+ fn infer_multiple_negate_bool (
884
+ & mut self ,
885
+ starting_location : SrcSpan ,
886
+ negations : usize ,
887
+ location : SrcSpan ,
888
+ value : UntypedExpr ,
889
+ ) -> TypedExpr {
890
+ // If we're typing a double negation we just keep going increasing the
891
+ // number of consecutive negations, inferring the wrapped value.
892
+ if let UntypedExpr :: NegateBool {
893
+ location : inner_location,
894
+ value,
895
+ } = value
896
+ {
897
+ return TypedExpr :: NegateBool {
898
+ location,
899
+ value : Box :: new ( self . infer_multiple_negate_bool (
900
+ starting_location,
901
+ negations + 1 ,
902
+ inner_location,
903
+ * value,
904
+ ) ) ,
905
+ } ;
906
+ }
907
+
908
+ // We know the last value can't be a bool negation if we're here, so
909
+ // we're ready to produce a typed value!
910
+ let value = self . infer ( value) ;
882
911
if let Err ( error) = unify ( bool ( ) , value. type_ ( ) ) {
883
912
self . problems
884
- . error ( convert_unify_error ( error, value. location ( ) ) )
913
+ . error ( convert_unify_error ( error, value. location ( ) ) ) ;
885
914
}
886
915
887
- if let TypedExpr :: NegateBool {
888
- location : inner_location,
889
- ..
890
- } = value
891
- {
916
+ // If there's more than a single negation we can raise a warning
917
+ // highlighting the unneded ones. How many negations are highlighted
918
+ // depends if they're an even or odd number:
919
+ //
920
+ // ```gleam
921
+ // !!True // all negations are superfluous.
922
+ // !!!True // we can remove all but one negation.
923
+ // ```
924
+ if negations > 1 {
925
+ let location = if negations % 2 == 0 {
926
+ SrcSpan {
927
+ start : starting_location. start ,
928
+ end : location. start + 1 ,
929
+ }
930
+ } else {
931
+ SrcSpan {
932
+ start : starting_location. start ,
933
+ end : location. start ,
934
+ }
935
+ } ;
936
+
892
937
self . problems
893
- . warning ( Warning :: UnnecessaryDoubleBoolNegation {
894
- location : SrcSpan {
895
- start : location. start ,
896
- end : inner_location. start + 1 ,
897
- } ,
898
- } ) ;
938
+ . warning ( Warning :: UnnecessaryDoubleBoolNegation { location } ) ;
899
939
}
900
940
901
941
TypedExpr :: NegateBool {
@@ -905,41 +945,82 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
905
945
}
906
946
907
947
fn infer_negate_int ( & mut self , location : SrcSpan , value : UntypedExpr ) -> TypedExpr {
908
- let value = self . infer ( value) ;
948
+ self . infer_multiple_negate_int ( location, 1 , location, value)
949
+ }
909
950
951
+ fn infer_multiple_negate_int (
952
+ & mut self ,
953
+ starting_location : SrcSpan ,
954
+ mut negations : usize ,
955
+ location : SrcSpan ,
956
+ value : UntypedExpr ,
957
+ ) -> TypedExpr {
958
+ // If we're typing a double negation we just keep going increasing the
959
+ // number of consecutive negations, inferring the wrapped value.
960
+ if let UntypedExpr :: NegateInt {
961
+ location : inner_location,
962
+ value,
963
+ } = value
964
+ {
965
+ return TypedExpr :: NegateInt {
966
+ location,
967
+ value : Box :: new ( self . infer_multiple_negate_int (
968
+ starting_location,
969
+ negations + 1 ,
970
+ inner_location,
971
+ * value,
972
+ ) ) ,
973
+ } ;
974
+ }
975
+
976
+ // We know the last value can't be an int negation, so we're ready to
977
+ // produce a typed value!
978
+ let value = self . infer ( value) ;
910
979
if let Err ( error) = unify ( int ( ) , value. type_ ( ) ) {
911
980
self . problems
912
981
. error ( convert_unify_error ( error, value. location ( ) ) ) ;
913
982
}
914
983
984
+ // This is used to emit a warning in case there's multiple negations.
985
+ let mut end = location. start ;
986
+
987
+ // There's one special case where the final integer being typed might be
988
+ // negated as well, in that case we need to update the number of
989
+ // consecutive negations.
915
990
if let TypedExpr :: Int {
916
991
value : ref v,
917
- location : ref inner_location ,
992
+ ref location ,
918
993
..
919
994
} = value
920
995
&& v. starts_with ( '-' )
921
996
{
922
- self . problems
923
- . warning ( Warning :: UnnecessaryDoubleIntNegation {
924
- location : SrcSpan {
925
- start : location. start ,
926
- end : inner_location. start + 1 ,
927
- } ,
928
- } ) ;
997
+ negations += 1 ;
998
+ end = location. start ;
929
999
}
930
1000
931
- if let TypedExpr :: NegateInt {
932
- location : inner_location,
933
- ..
934
- } = value
935
- {
1001
+ // If there's more than a single negation we can raise a warning
1002
+ // highlighting the unneded ones. How many negations are highlighted
1003
+ // depends if they're an even or odd number:
1004
+ //
1005
+ // ```gleam
1006
+ // --1 // all negations are superfluous.
1007
+ // ---1 // we can remove all but one negation.
1008
+ // ```
1009
+ if negations > 1 {
1010
+ let location = if negations % 2 == 0 {
1011
+ SrcSpan {
1012
+ start : starting_location. start ,
1013
+ end : end + 1 ,
1014
+ }
1015
+ } else {
1016
+ SrcSpan {
1017
+ start : starting_location. start ,
1018
+ end,
1019
+ }
1020
+ } ;
1021
+
936
1022
self . problems
937
- . warning ( Warning :: UnnecessaryDoubleIntNegation {
938
- location : SrcSpan {
939
- start : location. start ,
940
- end : inner_location. start + 1 ,
941
- } ,
942
- } ) ;
1023
+ . warning ( Warning :: UnnecessaryDoubleIntNegation { location } ) ;
943
1024
}
944
1025
945
1026
TypedExpr :: NegateInt {
0 commit comments