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>
@@ -655,12 +657,12 @@ static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname
655657 return 0 ;
656658}
657659
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
659661{
660662 size_t n = 0 ;
661663 if (wrap )
662664 n += jl_printf (out , "\"" );
663- if (!u8_isvalid (str , len )) {
665+ if (!raw && ! u8_isvalid (str , len )) {
664666 // alternate print algorithm that preserves data if it's not UTF-8
665667 static const char hexdig [] = "0123456789abcdef" ;
666668 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,
677679 int special = 0 ;
678680 for (size_t i = 0 ; i < len ; i ++ ) {
679681 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 == '$' )) {
681687 special = 1 ;
682688 break ;
683689 }
@@ -686,6 +692,25 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
686692 jl_uv_puts (out , str , len );
687693 n += len ;
688694 }
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+ }
689714 else {
690715 char buf [512 ];
691716 size_t i = 0 ;
@@ -701,18 +726,28 @@ static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len,
701726 return n ;
702727}
703728
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).
704741static size_t jl_static_show_symbol (JL_STREAM * out , jl_sym_t * name ) JL_NOTSAFEPOINT
705742{
706743 size_t n = 0 ;
707744 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 );
713747 }
714748 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 );
716751 }
717752 return n ;
718753}
@@ -741,6 +776,51 @@ static int jl_static_is_function_(jl_datatype_t *vt) JL_NOTSAFEPOINT {
741776 return 0 ;
742777}
743778
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+
744824// `v` might be pointing to a field inlined in a structure therefore
745825// `jl_typeof(v)` may not be the same with `vt` and only `vt` should be
746826// 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
906986 int f = * (uint32_t * )jl_data_ptr (v );
907987 n += jl_printf (out , "#<intrinsic #%d %s>" , f , jl_intrinsic_name (f ));
908988 }
989+ else if (vt == jl_long_type ) {
990+ // Avoid unnecessary Int64(x)/Int32(x)
991+ n += jl_printf (out , "%" PRIdPTR , * (intptr_t * )v );
992+ }
909993 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 );
911995 }
912996 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 );
914998 }
915999 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 );
9171001 }
9181002 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 );
9201004 }
9211005 else if (vt == jl_uint64_type ) {
9221006 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
9371021 n += jl_printf (out , "0x%08" PRIx32 , * (uint32_t * )v );
9381022#endif
9391023 }
1024+ else if (vt == jl_float16_type ) {
1025+ n += jl_static_show_float (out , julia__gnu_h2f_ieee (* (uint16_t * )v ), vt );
1026+ }
9401027 else if (vt == jl_float32_type ) {
941- n += jl_printf (out , "%gf" , * (float * )v );
1028+ n += jl_static_show_float (out , * (float * )v , vt );
9421029 }
9431030 else if (vt == jl_float64_type ) {
944- n += jl_printf (out , "%g" , * (double * )v );
1031+ n += jl_static_show_float (out , * (double * )v , vt );
9451032 }
9461033 else if (vt == jl_bool_type ) {
9471034 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
9501037 n += jl_printf (out , "nothing" );
9511038 }
9521039 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 );
9541041 }
9551042 else if (v == jl_bottom_type ) {
9561043 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,
14421529 }
14431530 jl_printf (str , "\n@ " );
14441531 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 );
14461533 }
14471534 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 );
14491536 }
14501537 jl_printf (str , ":" );
14511538 jl_static_show (str , line );
0 commit comments