5
5
*/
6
6
#include "platform.h"
7
7
8
+ #include <float.h>
9
+ #include <math.h>
8
10
#include <stdlib.h>
9
11
#include <stdio.h>
10
12
#include <string.h>
@@ -691,12 +693,12 @@ static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname
691
693
return 0 ;
692
694
}
693
695
694
- static size_t jl_static_show_string (JL_STREAM * out , const char * str , size_t len , int wrap ) JL_NOTSAFEPOINT
696
+ static size_t jl_static_show_string (JL_STREAM * out , const char * str , size_t len , int wrap , int raw ) JL_NOTSAFEPOINT
695
697
{
696
698
size_t n = 0 ;
697
699
if (wrap )
698
700
n += jl_printf (out , "\"" );
699
- if (!u8_isvalid (str , len )) {
701
+ if (!raw && ! u8_isvalid (str , len )) {
700
702
// alternate print algorithm that preserves data if it's not UTF-8
701
703
static const char hexdig [] = "0123456789abcdef" ;
702
704
for (size_t i = 0 ; i < len ; i ++ ) {
@@ -713,7 +715,11 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
713
715
int special = 0 ;
714
716
for (size_t i = 0 ; i < len ; i ++ ) {
715
717
uint8_t c = str [i ];
716
- if (c < 32 || c == 0x7f || c == '\\' || c == '"' || c == '$' ) {
718
+ if (raw && ((c == '\\' && i == len - 1 ) || c == '"' )) {
719
+ special = 1 ;
720
+ break ;
721
+ }
722
+ else if (!raw && (c < 32 || c == 0x7f || c == '\\' || c == '"' || c == '$' )) {
717
723
special = 1 ;
718
724
break ;
719
725
}
@@ -722,6 +728,25 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
722
728
jl_uv_puts (out , str , len );
723
729
n += len ;
724
730
}
731
+ else if (raw ) {
732
+ // REF: Base.escape_raw_string
733
+ int escapes = 0 ;
734
+ for (size_t i = 0 ; i < len ; i ++ ) {
735
+ uint8_t c = str [i ];
736
+ if (c == '\\' ) {
737
+ escapes ++ ;
738
+ }
739
+ else {
740
+ if (c == '"' )
741
+ for (escapes ++ ; escapes > 0 ; escapes -- )
742
+ n += jl_printf (out , "\\" );
743
+ escapes = 0 ;
744
+ }
745
+ n += jl_printf (out , "%c" , str [i ]);
746
+ }
747
+ for (; escapes > 0 ; escapes -- )
748
+ n += jl_printf (out , "\\" );
749
+ }
725
750
else {
726
751
char buf [512 ];
727
752
size_t i = 0 ;
@@ -737,18 +762,28 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
737
762
return n ;
738
763
}
739
764
765
+ static int jl_is_quoted_sym (const char * sn )
766
+ {
767
+ static const char * const quoted_syms [] = {":" , "::" , ":=" , "=" , "==" , "===" , "=>" , "`" };
768
+ for (int i = 0 ; i < sizeof quoted_syms / sizeof * quoted_syms ; i ++ )
769
+ if (!strcmp (sn , quoted_syms [i ]))
770
+ return 1 ;
771
+ return 0 ;
772
+ }
773
+
774
+ // TODO: in theory, we need a separate function for showing symbols in an
775
+ // expression context (where `Symbol("foo\x01bar")` is ok) and a syntactic
776
+ // context (where var"" must be used).
740
777
static size_t jl_static_show_symbol (JL_STREAM * out , jl_sym_t * name ) JL_NOTSAFEPOINT
741
778
{
742
779
size_t n = 0 ;
743
780
const char * sn = jl_symbol_name (name );
744
- int quoted = !jl_is_identifier (sn ) && !jl_is_operator (sn );
745
- if (quoted ) {
746
- n += jl_printf (out , "var" );
747
- // TODO: this is not quite right, since repr uses String escaping rules, and Symbol uses raw string rules
748
- n += jl_static_show_string (out , sn , strlen (sn ), 1 );
781
+ if (jl_is_identifier (sn ) || (jl_is_operator (sn ) && !jl_is_quoted_sym (sn ))) {
782
+ n += jl_printf (out , "%s" , sn );
749
783
}
750
784
else {
751
- n += jl_printf (out , "%s" , sn );
785
+ n += jl_printf (out , "var" );
786
+ n += jl_static_show_string (out , sn , strlen (sn ), 1 , 1 );
752
787
}
753
788
return n ;
754
789
}
@@ -777,6 +812,51 @@ static int jl_static_is_function_(jl_datatype_t *vt) JL_NOTSAFEPOINT {
777
812
return 0 ;
778
813
}
779
814
815
+ static size_t jl_static_show_float (JL_STREAM * out , double v ,
816
+ jl_datatype_t * vt ) JL_NOTSAFEPOINT
817
+ {
818
+ size_t n = 0 ;
819
+ // TODO: non-canonical NaNs do not round-trip
820
+ // TOOD: BFloat16
821
+ const char * size_suffix = vt == jl_float16_type ? "16" :
822
+ vt == jl_float32_type ? "32" :
823
+ "" ;
824
+ // Requires minimum 1 (sign) + 17 (sig) + 1 (dot) + 5 ("e-123") + 1 (null)
825
+ char buf [32 ];
826
+ // Base B significand digits required to print n base-b significand bits
827
+ // (including leading 1): N = 2 + floor(n/log(b, B))
828
+ // Float16 5
829
+ // Float32 9
830
+ // Float64 17
831
+ // REF: https://dl.acm.org/doi/pdf/10.1145/93542.93559
832
+ if (isnan (v )) {
833
+ n += jl_printf (out , "NaN%s" , size_suffix );
834
+ }
835
+ else if (isinf (v )) {
836
+ n += jl_printf (out , "%sInf%s" , v < 0 ? "-" : "" , size_suffix );
837
+ }
838
+ else if (vt == jl_float64_type ) {
839
+ n += jl_printf (out , "%#.17g" , v );
840
+ }
841
+ else if (vt == jl_float32_type ) {
842
+ size_t m = snprintf (buf , sizeof buf , "%.9g" , v );
843
+ // If the exponent was printed, replace it with 'f'
844
+ char * p = (char * )memchr (buf , 'e' , m );
845
+ if (p )
846
+ * p = 'f' ;
847
+ jl_uv_puts (out , buf , m );
848
+ n += m ;
849
+ // If no exponent was printed, we must add one
850
+ if (!p )
851
+ n += jl_printf (out , "f0" );
852
+ }
853
+ else {
854
+ assert (vt == jl_float16_type );
855
+ n += jl_printf (out , "Float16(%#.5g)" , v );
856
+ }
857
+ return n ;
858
+ }
859
+
780
860
// `v` might be pointing to a field inlined in a structure therefore
781
861
// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
782
862
// used to determine the type of the value.
@@ -957,17 +1037,21 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
957
1037
int f = * (uint32_t * )jl_data_ptr (v );
958
1038
n += jl_printf (out , "#<intrinsic #%d %s>" , f , jl_intrinsic_name (f ));
959
1039
}
1040
+ else if (vt == jl_long_type ) {
1041
+ // Avoid unnecessary Int64(x)/Int32(x)
1042
+ n += jl_printf (out , "%" PRIdPTR , * (intptr_t * )v );
1043
+ }
960
1044
else if (vt == jl_int64_type ) {
961
- n += jl_printf (out , "%" PRId64 , * (int64_t * )v );
1045
+ n += jl_printf (out , "Int64( %" PRId64 ")" , * (int64_t * )v );
962
1046
}
963
1047
else if (vt == jl_int32_type ) {
964
- n += jl_printf (out , "%" PRId32 , * (int32_t * )v );
1048
+ n += jl_printf (out , "Int32( %" PRId32 ")" , * (int32_t * )v );
965
1049
}
966
1050
else if (vt == jl_int16_type ) {
967
- n += jl_printf (out , "%" PRId16 , * (int16_t * )v );
1051
+ n += jl_printf (out , "Int16( %" PRId16 ")" , * (int16_t * )v );
968
1052
}
969
1053
else if (vt == jl_int8_type ) {
970
- n += jl_printf (out , "%" PRId8 , * (int8_t * )v );
1054
+ n += jl_printf (out , "Int8( %" PRId8 ")" , * (int8_t * )v );
971
1055
}
972
1056
else if (vt == jl_uint64_type ) {
973
1057
n += jl_printf (out , "0x%016" PRIx64 , * (uint64_t * )v );
@@ -988,11 +1072,14 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
988
1072
n += jl_printf (out , "0x%08" PRIx32 , * (uint32_t * )v );
989
1073
#endif
990
1074
}
1075
+ else if (vt == jl_float16_type ) {
1076
+ n += jl_static_show_float (out , julia_half_to_float (* (uint16_t * )v ), vt );
1077
+ }
991
1078
else if (vt == jl_float32_type ) {
992
- n += jl_printf (out , "%gf" , * (float * )v );
1079
+ n += jl_static_show_float (out , * (float * )v , vt );
993
1080
}
994
1081
else if (vt == jl_float64_type ) {
995
- n += jl_printf (out , "%g" , * (double * )v );
1082
+ n += jl_static_show_float (out , * (double * )v , vt );
996
1083
}
997
1084
else if (vt == jl_bool_type ) {
998
1085
n += jl_printf (out , "%s" , * (uint8_t * )v ? "true" : "false" );
@@ -1004,7 +1091,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
1004
1091
n += jl_printf (out , "Core.GlobalMethods" );
1005
1092
}
1006
1093
else if (vt == jl_string_type ) {
1007
- n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 );
1094
+ n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 , 0 );
1008
1095
}
1009
1096
else if (v == jl_bottom_type ) {
1010
1097
n += jl_printf (out , "Union{}" );
@@ -1532,10 +1619,10 @@ void jl_log(int level, jl_value_t *module, jl_value_t *group, jl_value_t *id,
1532
1619
}
1533
1620
jl_printf (str , "\n@ " );
1534
1621
if (jl_is_string (file )) {
1535
- jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 );
1622
+ jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 , 0 );
1536
1623
}
1537
1624
else if (jl_is_symbol (file )) {
1538
- jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 );
1625
+ jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 , 0 );
1539
1626
}
1540
1627
jl_printf (str , ":" );
1541
1628
jl_static_show (str , line );
0 commit comments