55*/
66#include "platform.h"
77
8+ #include <float.h>
9+ #include <math.h>
810#include <stdlib.h>
911#include <stdio.h>
1012#include <string.h>
@@ -691,12 +693,12 @@ static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname
691693 return 0 ;
692694}
693695
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
695697{
696698 size_t n = 0 ;
697699 if (wrap )
698700 n += jl_printf (out , "\"" );
699- if (!u8_isvalid (str , len )) {
701+ if (!raw && ! u8_isvalid (str , len )) {
700702 // alternate print algorithm that preserves data if it's not UTF-8
701703 static const char hexdig [] = "0123456789abcdef" ;
702704 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,
713715 int special = 0 ;
714716 for (size_t i = 0 ; i < len ; i ++ ) {
715717 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 == '$' )) {
717723 special = 1 ;
718724 break ;
719725 }
@@ -722,6 +728,25 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
722728 jl_uv_puts (out , str , len );
723729 n += len ;
724730 }
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+ }
725750 else {
726751 char buf [512 ];
727752 size_t i = 0 ;
@@ -737,18 +762,28 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
737762 return n ;
738763}
739764
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).
740777static size_t jl_static_show_symbol (JL_STREAM * out , jl_sym_t * name ) JL_NOTSAFEPOINT
741778{
742779 size_t n = 0 ;
743780 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 );
749783 }
750784 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 );
752787 }
753788 return n ;
754789}
@@ -777,6 +812,51 @@ static int jl_static_is_function_(jl_datatype_t *vt) JL_NOTSAFEPOINT {
777812 return 0 ;
778813}
779814
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+
780860// `v` might be pointing to a field inlined in a structure therefore
781861// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
782862// used to determine the type of the value.
@@ -954,17 +1034,21 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
9541034 int f = * (uint32_t * )jl_data_ptr (v );
9551035 n += jl_printf (out , "#<intrinsic #%d %s>" , f , jl_intrinsic_name (f ));
9561036 }
1037+ else if (vt == jl_long_type ) {
1038+ // Avoid unnecessary Int64(x)/Int32(x)
1039+ n += jl_printf (out , "%" PRIdPTR , * (intptr_t * )v );
1040+ }
9571041 else if (vt == jl_int64_type ) {
958- n += jl_printf (out , "%" PRId64 , * (int64_t * )v );
1042+ n += jl_printf (out , "Int64( %" PRId64 ")" , * (int64_t * )v );
9591043 }
9601044 else if (vt == jl_int32_type ) {
961- n += jl_printf (out , "%" PRId32 , * (int32_t * )v );
1045+ n += jl_printf (out , "Int32( %" PRId32 ")" , * (int32_t * )v );
9621046 }
9631047 else if (vt == jl_int16_type ) {
964- n += jl_printf (out , "%" PRId16 , * (int16_t * )v );
1048+ n += jl_printf (out , "Int16( %" PRId16 ")" , * (int16_t * )v );
9651049 }
9661050 else if (vt == jl_int8_type ) {
967- n += jl_printf (out , "%" PRId8 , * (int8_t * )v );
1051+ n += jl_printf (out , "Int8( %" PRId8 ")" , * (int8_t * )v );
9681052 }
9691053 else if (vt == jl_uint64_type ) {
9701054 n += jl_printf (out , "0x%016" PRIx64 , * (uint64_t * )v );
@@ -985,11 +1069,14 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
9851069 n += jl_printf (out , "0x%08" PRIx32 , * (uint32_t * )v );
9861070#endif
9871071 }
1072+ else if (vt == jl_float16_type ) {
1073+ n += jl_static_show_float (out , julia_half_to_float (* (uint16_t * )v ), vt );
1074+ }
9881075 else if (vt == jl_float32_type ) {
989- n += jl_printf (out , "%gf" , * (float * )v );
1076+ n += jl_static_show_float (out , * (float * )v , vt );
9901077 }
9911078 else if (vt == jl_float64_type ) {
992- n += jl_printf (out , "%g" , * (double * )v );
1079+ n += jl_static_show_float (out , * (double * )v , vt );
9931080 }
9941081 else if (vt == jl_bool_type ) {
9951082 n += jl_printf (out , "%s" , * (uint8_t * )v ? "true" : "false" );
@@ -998,7 +1085,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
9981085 n += jl_printf (out , "nothing" );
9991086 }
10001087 else if (vt == jl_string_type ) {
1001- n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 );
1088+ n += jl_static_show_string (out , jl_string_data (v ), jl_string_len (v ), 1 , 0 );
10021089 }
10031090 else if (v == jl_bottom_type ) {
10041091 n += jl_printf (out , "Union{}" );
@@ -1528,10 +1615,10 @@ void jl_log(int level, jl_value_t *module, jl_value_t *group, jl_value_t *id,
15281615 }
15291616 jl_printf (str , "\n@ " );
15301617 if (jl_is_string (file )) {
1531- jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 );
1618+ jl_static_show_string (str , jl_string_data (file ), jl_string_len (file ), 0 , 0 );
15321619 }
15331620 else if (jl_is_symbol (file )) {
1534- jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 );
1621+ jl_static_show_string (str , jl_symbol_name ((jl_sym_t * )file ), strlen (jl_symbol_name ((jl_sym_t * )file )), 0 , 0 );
15351622 }
15361623 jl_printf (str , ":" );
15371624 jl_static_show (str , line );
0 commit comments