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>
@@ -655,12 +657,12 @@ static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname
655
657
return 0 ;
656
658
}
657
659
658
- static size_t jl_static_show_string (JL_STREAM * out , const char * str , size_t len , int wrap ) JL_NOTSAFEPOINT
660
+ static size_t jl_static_show_string (JL_STREAM * out , const char * str , size_t len , int wrap , int raw ) JL_NOTSAFEPOINT
659
661
{
660
662
size_t n = 0 ;
661
663
if (wrap )
662
664
n += jl_printf (out , "\"" );
663
- if (!u8_isvalid (str , len )) {
665
+ if (!raw && ! u8_isvalid (str , len )) {
664
666
// alternate print algorithm that preserves data if it's not UTF-8
665
667
static const char hexdig [] = "0123456789abcdef" ;
666
668
for (size_t i = 0 ; i < len ; i ++ ) {
@@ -677,7 +679,11 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
677
679
int special = 0 ;
678
680
for (size_t i = 0 ; i < len ; i ++ ) {
679
681
uint8_t c = str [i ];
680
- if (c < 32 || c == 0x7f || c == '\\' || c == '"' || c == '$' ) {
682
+ if (raw && ((c == '\\' && i == len - 1 ) || c == '"' )) {
683
+ special = 1 ;
684
+ break ;
685
+ }
686
+ else if (!raw && (c < 32 || c == 0x7f || c == '\\' || c == '"' || c == '$' )) {
681
687
special = 1 ;
682
688
break ;
683
689
}
@@ -686,6 +692,25 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
686
692
jl_uv_puts (out , str , len );
687
693
n += len ;
688
694
}
695
+ else if (raw ) {
696
+ // REF: Base.escape_raw_string
697
+ int escapes = 0 ;
698
+ for (size_t i = 0 ; i < len ; i ++ ) {
699
+ uint8_t c = str [i ];
700
+ if (c == '\\' ) {
701
+ escapes ++ ;
702
+ }
703
+ else {
704
+ if (c == '"' )
705
+ for (escapes ++ ; escapes > 0 ; escapes -- )
706
+ n += jl_printf (out , "\\" );
707
+ escapes = 0 ;
708
+ }
709
+ n += jl_printf (out , "%c" , str [i ]);
710
+ }
711
+ for (; escapes > 0 ; escapes -- )
712
+ n += jl_printf (out , "\\" );
713
+ }
689
714
else {
690
715
char buf [512 ];
691
716
size_t i = 0 ;
@@ -701,18 +726,28 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
701
726
return n ;
702
727
}
703
728
729
+ static int jl_is_quoted_sym (const char * sn )
730
+ {
731
+ static const char * const quoted_syms [] = {":" , "::" , ":=" , "=" , "==" , "===" , "=>" , "`" };
732
+ for (int i = 0 ; i < sizeof quoted_syms / sizeof * quoted_syms ; i ++ )
733
+ if (!strcmp (sn , quoted_syms [i ]))
734
+ return 1 ;
735
+ return 0 ;
736
+ }
737
+
738
+ // TODO: in theory, we need a separate function for showing symbols in an
739
+ // expression context (where `Symbol("foo\x01bar")` is ok) and a syntactic
740
+ // context (where var"" must be used).
704
741
static size_t jl_static_show_symbol (JL_STREAM * out , jl_sym_t * name ) JL_NOTSAFEPOINT
705
742
{
706
743
size_t n = 0 ;
707
744
const char * sn = jl_symbol_name (name );
708
- int quoted = !jl_is_identifier (sn ) && !jl_is_operator (sn );
709
- if (quoted ) {
710
- n += jl_printf (out , "var" );
711
- // TODO: this is not quite right, since repr uses String escaping rules, and Symbol uses raw string rules
712
- n += jl_static_show_string (out , sn , strlen (sn ), 1 );
745
+ if (jl_is_identifier (sn ) || (jl_is_operator (sn ) && !jl_is_quoted_sym (sn ))) {
746
+ n += jl_printf (out , "%s" , sn );
713
747
}
714
748
else {
715
- n += jl_printf (out , "%s" , sn );
749
+ n += jl_printf (out , "var" );
750
+ n += jl_static_show_string (out , sn , strlen (sn ), 1 , 1 );
716
751
}
717
752
return n ;
718
753
}
@@ -741,6 +776,51 @@ static int jl_static_is_function_(jl_datatype_t *vt) JL_NOTSAFEPOINT {
741
776
return 0 ;
742
777
}
743
778
779
+ static size_t jl_static_show_float (JL_STREAM * out , double v ,
780
+ jl_datatype_t * vt ) JL_NOTSAFEPOINT
781
+ {
782
+ size_t n = 0 ;
783
+ // TODO: non-canonical NaNs do not round-trip
784
+ // TOOD: BFloat16
785
+ const char * size_suffix = vt == jl_float16_type ? "16" :
786
+ vt == jl_float32_type ? "32" :
787
+ "" ;
788
+ // Requires minimum 1 (sign) + 17 (sig) + 1 (dot) + 5 ("e-123") + 1 (null)
789
+ char buf [32 ];
790
+ // Base B significand digits required to print n base-b significand bits
791
+ // (including leading 1): N = 2 + floor(n/log(b, B))
792
+ // Float16 5
793
+ // Float32 9
794
+ // Float64 17
795
+ // REF: https://dl.acm.org/doi/pdf/10.1145/93542.93559
796
+ if (isnan (v )) {
797
+ n += jl_printf (out , "NaN%s" , size_suffix );
798
+ }
799
+ else if (isinf (v )) {
800
+ n += jl_printf (out , "%sInf%s" , v < 0 ? "-" : "" , size_suffix );
801
+ }
802
+ else if (vt == jl_float64_type ) {
803
+ n += jl_printf (out , "%#.17g" , v );
804
+ }
805
+ else if (vt == jl_float32_type ) {
806
+ size_t m = snprintf (buf , sizeof buf , "%.9g" , v );
807
+ // If the exponent was printed, replace it with 'f'
808
+ char * p = (char * )memchr (buf , 'e' , m );
809
+ if (p )
810
+ * p = 'f' ;
811
+ jl_uv_puts (out , buf , m );
812
+ n += m ;
813
+ // If no exponent was printed, we must add one
814
+ if (!p )
815
+ n += jl_printf (out , "f0" );
816
+ }
817
+ else {
818
+ assert (vt == jl_float16_type );
819
+ n += jl_printf (out , "Float16(%#.5g)" , v );
820
+ }
821
+ return n ;
822
+ }
823
+
744
824
// `v` might be pointing to a field inlined in a structure therefore
745
825
// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
746
826
// used to determine the type of the value.
@@ -906,17 +986,21 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
906
986
int f = * (uint32_t * )jl_data_ptr (v );
907
987
n += jl_printf (out , "#<intrinsic #%d %s>" , f , jl_intrinsic_name (f ));
908
988
}
989
+ else if (vt == jl_long_type ) {
990
+ // Avoid unnecessary Int64(x)/Int32(x)
991
+ n += jl_printf (out , "%" PRIdPTR , * (intptr_t * )v );
992
+ }
909
993
else if (vt == jl_int64_type ) {
910
- n += jl_printf (out , "%" PRId64 , * (int64_t * )v );
994
+ n += jl_printf (out , "Int64( %" PRId64 ")" , * (int64_t * )v );
911
995
}
912
996
else if (vt == jl_int32_type ) {
913
- n += jl_printf (out , "%" PRId32 , * (int32_t * )v );
997
+ n += jl_printf (out , "Int32( %" PRId32 ")" , * (int32_t * )v );
914
998
}
915
999
else if (vt == jl_int16_type ) {
916
- n += jl_printf (out , "%" PRId16 , * (int16_t * )v );
1000
+ n += jl_printf (out , "Int16( %" PRId16 ")" , * (int16_t * )v );
917
1001
}
918
1002
else if (vt == jl_int8_type ) {
919
- n += jl_printf (out , "%" PRId8 , * (int8_t * )v );
1003
+ n += jl_printf (out , "Int8( %" PRId8 ")" , * (int8_t * )v );
920
1004
}
921
1005
else if (vt == jl_uint64_type ) {
922
1006
n += jl_printf (out , "0x%016" PRIx64 , * (uint64_t * )v );
@@ -937,11 +1021,14 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
937
1021
n += jl_printf (out , "0x%08" PRIx32 , * (uint32_t * )v );
938
1022
#endif
939
1023
}
1024
+ else if (vt == jl_float16_type ) {
1025
+ n += jl_static_show_float (out , julia__gnu_h2f_ieee (* (uint16_t * )v ), vt );
1026
+ }
940
1027
else if (vt == jl_float32_type ) {
941
- n += jl_printf (out , "%gf" , * (float * )v );
1028
+ n += jl_static_show_float (out , * (float * )v , vt );
942
1029
}
943
1030
else if (vt == jl_float64_type ) {
944
- n += jl_printf (out , "%g" , * (double * )v );
1031
+ n += jl_static_show_float (out , * (double * )v , vt );
945
1032
}
946
1033
else if (vt == jl_bool_type ) {
947
1034
n += jl_printf (out , "%s" , * (uint8_t * )v ? "true" : "false" );
@@ -950,7 +1037,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
950
1037
n += jl_printf (out , "nothing" );
951
1038
}
952
1039
else if (vt == jl_string_type ) {
953
- n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 );
1040
+ n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 , 0 );
954
1041
}
955
1042
else if (v == jl_bottom_type ) {
956
1043
n += jl_printf (out , "Union{}" );
@@ -1442,10 +1529,10 @@ void jl_log(int level, jl_value_t *module, jl_value_t *group, jl_value_t *id,
1442
1529
}
1443
1530
jl_printf (str , "\n@ " );
1444
1531
if (jl_is_string (file )) {
1445
- jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 );
1532
+ jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 , 0 );
1446
1533
}
1447
1534
else if (jl_is_symbol (file )) {
1448
- jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 );
1535
+ jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 , 0 );
1449
1536
}
1450
1537
jl_printf (str , ":" );
1451
1538
jl_static_show (str , line );
0 commit comments