Skip to content

Commit 33e8cfe

Browse files
jishnubvtjnash
authored andcommitted
static-show: improve accuracy of some printings
- Show strings with escaping, rather than trying to output the text unmodified. - Show symbols with the same formatting as Strings - Avoid accidentally defining a broken Core.show method for NamedTuple
1 parent 5643c60 commit 33e8cfe

File tree

10 files changed

+126
-78
lines changed

10 files changed

+126
-78
lines changed

base/namedtuple.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,8 @@ function convert(::Type{NT}, nt::NamedTuple{names}) where {names, NT<:NamedTuple
196196
end
197197

198198
if nameof(@__MODULE__) === :Base
199-
Tuple(nt::NamedTuple) = (nt...,)
200-
(::Type{T})(nt::NamedTuple) where {T <: Tuple} = (t = Tuple(nt); t isa T ? t : convert(T, t)::T)
201-
end
199+
Tuple(nt::NamedTuple) = (nt...,)
200+
(::Type{T})(nt::NamedTuple) where {T <: Tuple} = (t = Tuple(nt); t isa T ? t : convert(T, t)::T)
202201

203202
function show(io::IO, t::NamedTuple)
204203
n = nfields(t)
@@ -232,6 +231,7 @@ function show(io::IO, t::NamedTuple)
232231
print(io, ")")
233232
end
234233
end
234+
end
235235

236236
eltype(::Type{T}) where T<:NamedTuple = nteltype(T)
237237
nteltype(::Type) = Any

base/show.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1792,7 +1792,7 @@ function show_sym(io::IO, sym::Symbol; allow_macroname=false)
17921792
print(io, '@')
17931793
show_sym(io, Symbol(sym_str[2:end]))
17941794
else
1795-
print(io, "var", repr(string(sym)))
1795+
print(io, "var", repr(string(sym))) # TODO: this is not quite right, since repr uses String escaping rules, and Symbol uses raw string rules
17961796
end
17971797
end
17981798

src/ast.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ JL_DLLEXPORT jl_value_t *jl_copy_ast(jl_value_t *expr)
990990
return expr;
991991
}
992992

993-
JL_DLLEXPORT int jl_is_operator(char *sym)
993+
JL_DLLEXPORT int jl_is_operator(const char *sym)
994994
{
995995
jl_ast_context_t *ctx = jl_ast_ctx_enter(NULL);
996996
fl_context_t *fl_ctx = &ctx->fl;
@@ -999,7 +999,7 @@ JL_DLLEXPORT int jl_is_operator(char *sym)
999999
return res;
10001000
}
10011001

1002-
JL_DLLEXPORT int jl_is_unary_operator(char *sym)
1002+
JL_DLLEXPORT int jl_is_unary_operator(const char *sym)
10031003
{
10041004
jl_ast_context_t *ctx = jl_ast_ctx_enter(NULL);
10051005
fl_context_t *fl_ctx = &ctx->fl;
@@ -1008,7 +1008,7 @@ JL_DLLEXPORT int jl_is_unary_operator(char *sym)
10081008
return res;
10091009
}
10101010

1011-
JL_DLLEXPORT int jl_is_unary_and_binary_operator(char *sym)
1011+
JL_DLLEXPORT int jl_is_unary_and_binary_operator(const char *sym)
10121012
{
10131013
jl_ast_context_t *ctx = jl_ast_ctx_enter(NULL);
10141014
fl_context_t *fl_ctx = &ctx->fl;
@@ -1017,7 +1017,7 @@ JL_DLLEXPORT int jl_is_unary_and_binary_operator(char *sym)
10171017
return res;
10181018
}
10191019

1020-
JL_DLLEXPORT int jl_is_syntactic_operator(char *sym)
1020+
JL_DLLEXPORT int jl_is_syntactic_operator(const char *sym)
10211021
{
10221022
jl_ast_context_t *ctx = jl_ast_ctx_enter(NULL);
10231023
fl_context_t *fl_ctx = &ctx->fl;
@@ -1026,7 +1026,7 @@ JL_DLLEXPORT int jl_is_syntactic_operator(char *sym)
10261026
return res;
10271027
}
10281028

1029-
JL_DLLEXPORT int jl_operator_precedence(char *sym)
1029+
JL_DLLEXPORT int jl_operator_precedence(const char *sym)
10301030
{
10311031
jl_ast_context_t *ctx = jl_ast_ctx_enter(NULL);
10321032
fl_context_t *fl_ctx = &ctx->fl;

src/flisp/print.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ static void print_string(fl_context_t *fl_ctx, ios_t *f, char *str, size_t sz)
518518
}
519519
else {
520520
while (i < sz) {
521-
size_t n = u8_escape(buf, sizeof(buf), str, &i, sz, 1, 0);
521+
size_t n = u8_escape(buf, sizeof(buf), str, &i, sz, "\"", 0);
522522
outsn(fl_ctx, buf, f, n-1);
523523
}
524524
}

src/julia.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2125,11 +2125,11 @@ JL_DLLEXPORT jl_array_t *jl_uncompress_argnames(jl_value_t *syms);
21252125
JL_DLLEXPORT jl_value_t *jl_uncompress_argname_n(jl_value_t *syms, size_t i);
21262126

21272127

2128-
JL_DLLEXPORT int jl_is_operator(char *sym);
2129-
JL_DLLEXPORT int jl_is_unary_operator(char *sym);
2130-
JL_DLLEXPORT int jl_is_unary_and_binary_operator(char *sym);
2131-
JL_DLLEXPORT int jl_is_syntactic_operator(char *sym);
2132-
JL_DLLEXPORT int jl_operator_precedence(char *sym);
2128+
JL_DLLEXPORT int jl_is_operator(const char *sym);
2129+
JL_DLLEXPORT int jl_is_unary_operator(const char *sym);
2130+
JL_DLLEXPORT int jl_is_unary_and_binary_operator(const char *sym);
2131+
JL_DLLEXPORT int jl_is_syntactic_operator(const char *sym);
2132+
JL_DLLEXPORT int jl_operator_precedence(const char *sym);
21332133

21342134
STATIC_INLINE int jl_vinfo_sa(uint8_t vi)
21352135
{

src/rtutils.c

Lines changed: 90 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ static size_t jl_show_svec(JL_STREAM *out, jl_svec_t *t, const char *head, const
591591
JL_DLLEXPORT int jl_id_start_char(uint32_t wc) JL_NOTSAFEPOINT;
592592
JL_DLLEXPORT int jl_id_char(uint32_t wc) JL_NOTSAFEPOINT;
593593

594-
JL_DLLEXPORT int jl_is_identifier(char *str) JL_NOTSAFEPOINT
594+
JL_DLLEXPORT int jl_is_identifier(const char *str) JL_NOTSAFEPOINT
595595
{
596596
size_t i = 0;
597597
uint32_t wc = u8_nextchar(str, &i);
@@ -674,22 +674,64 @@ static int is_globfunction(jl_value_t *v, jl_datatype_t *dv, jl_sym_t **globname
674674
return 0;
675675
}
676676

677-
static size_t jl_static_show_x_sym_escaped(JL_STREAM *out, jl_sym_t *name) JL_NOTSAFEPOINT
677+
static size_t jl_static_show_string(JL_STREAM *out, const char *str, size_t len, int wrap) JL_NOTSAFEPOINT
678678
{
679679
size_t n = 0;
680-
681-
char *sn = jl_symbol_name(name);
682-
int hidden = 0;
683-
if (!(jl_is_identifier(sn) || jl_is_operator(sn))) {
684-
hidden = 1;
680+
if (wrap)
681+
n += jl_printf(out, "\"");
682+
if (!u8_isvalid(str, len)) {
683+
// alternate print algorithm that preserves data if it's not UTF-8
684+
static const char hexdig[] = "0123456789abcdef";
685+
for (size_t i = 0; i < len; i++) {
686+
uint8_t c = str[i];
687+
if (c == '\\' || c == '"' || c == '$')
688+
n += jl_printf(out, "\\%c", c);
689+
else if (c >= 32 && c < 0x7f)
690+
n += jl_printf(out, "%c", c);
691+
else
692+
n += jl_printf(out, "\\x%c%c", hexdig[c>>4], hexdig[c&0xf]);
693+
}
685694
}
686-
687-
if (hidden) {
688-
n += jl_printf(out, "var\"");
695+
else {
696+
int special = 0;
697+
for (size_t i = 0; i < len; i++) {
698+
uint8_t c = str[i];
699+
if (c < 32 || c == 0x7f || c == '\\' || c == '"' || c == '$') {
700+
special = 1;
701+
break;
702+
}
703+
}
704+
if (!special) {
705+
jl_uv_puts(out, str, len);
706+
n += len;
707+
}
708+
else {
709+
char buf[512];
710+
size_t i = 0;
711+
while (i < len) {
712+
size_t r = u8_escape(buf, sizeof(buf), str, &i, len, "\"$", 0);
713+
jl_uv_puts(out, buf, r - 1);
714+
n += r - 1;
715+
}
716+
}
689717
}
690-
n += jl_printf(out, "%s", sn);
691-
if (hidden) {
718+
if (wrap)
692719
n += jl_printf(out, "\"");
720+
return n;
721+
}
722+
723+
static size_t jl_static_show_symbol(JL_STREAM *out, jl_sym_t *name) JL_NOTSAFEPOINT
724+
{
725+
size_t n = 0;
726+
const char *sn = jl_symbol_name(name);
727+
int quoted = !jl_is_identifier(sn) && !jl_is_operator(sn);
728+
if (quoted) {
729+
n += jl_printf(out, "var");
730+
// TODO: this is not quite right, since repr uses String escaping rules, and Symbol uses raw string rules
731+
n += jl_static_show_string(out, sn, strlen(sn), 1);
732+
}
733+
else {
734+
n += jl_printf(out, "%s", sn);
693735
}
694736
return n;
695737
}
@@ -807,11 +849,6 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
807849
// Types are printed as a fully qualified name, with parameters, e.g.
808850
// `Base.Set{Int}`, and function types are printed as e.g. `typeof(Main.f)`
809851
jl_datatype_t *dv = (jl_datatype_t*)v;
810-
jl_sym_t *globname;
811-
int globfunc = is_globname_binding(v, dv) && is_globfunction(v, dv, &globname);
812-
jl_sym_t *sym = globfunc ? globname : dv->name->name;
813-
char *sn = jl_symbol_name(sym);
814-
size_t quote = 0;
815852
if (dv->name == jl_tuple_typename) {
816853
if (dv == jl_tuple_type)
817854
return jl_printf(out, "Tuple");
@@ -844,8 +881,13 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
844881
return n;
845882
}
846883
if (ctx.quiet) {
847-
return jl_printf(out, "%s", jl_symbol_name(dv->name->name));
884+
return jl_static_show_symbol(out, dv->name->name);
848885
}
886+
jl_sym_t *globname;
887+
int globfunc = is_globname_binding(v, dv) && is_globfunction(v, dv, &globname);
888+
jl_sym_t *sym = globfunc ? globname : dv->name->name;
889+
char *sn = jl_symbol_name(sym);
890+
size_t quote = 0;
849891
if (globfunc) {
850892
n += jl_printf(out, "typeof(");
851893
}
@@ -858,7 +900,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
858900
quote = 1;
859901
}
860902
}
861-
n += jl_static_show_x_sym_escaped(out, sym);
903+
n += jl_static_show_symbol(out, sym);
862904
if (globfunc) {
863905
n += jl_printf(out, ")");
864906
if (quote) {
@@ -927,9 +969,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
927969
n += jl_printf(out, "nothing");
928970
}
929971
else if (vt == jl_string_type) {
930-
n += jl_printf(out, "\"");
931-
jl_uv_puts(out, jl_string_data(v), jl_string_len(v)); n += jl_string_len(v);
932-
n += jl_printf(out, "\"");
972+
n += jl_static_show_string(out, jl_string_data(v), jl_string_len(v), 1);
933973
}
934974
else if (v == jl_bottom_type) {
935975
n += jl_printf(out, "Union{}");
@@ -978,7 +1018,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
9781018
n += jl_printf(out, ")");
9791019
n += jl_printf(out, "<:");
9801020
}
981-
n += jl_static_show_x_sym_escaped(out, var->name);
1021+
n += jl_static_show_symbol(out, var->name);
9821022
if (showbounds && (ub != (jl_value_t*)jl_any_type || lb != jl_bottom_type)) {
9831023
// show type-var upper bound if it is defined, or if we showed the lower bound
9841024
int ua = jl_is_unionall(ub);
@@ -996,27 +1036,24 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
9961036
n += jl_static_show_x(out, (jl_value_t*)m->parent, depth, ctx);
9971037
n += jl_printf(out, ".");
9981038
}
999-
n += jl_printf(out, "%s", jl_symbol_name(m->name));
1039+
n += jl_static_show_symbol(out, m->name);
10001040
}
10011041
else if (vt == jl_symbol_type) {
1002-
char *sn = jl_symbol_name((jl_sym_t*)v);
1003-
int quoted = !jl_is_identifier(sn) && jl_operator_precedence(sn) == 0;
1004-
if (quoted)
1005-
n += jl_printf(out, "Symbol(\"");
1006-
else
1007-
n += jl_printf(out, ":");
1008-
n += jl_printf(out, "%s", sn);
1009-
if (quoted)
1010-
n += jl_printf(out, "\")");
1042+
n += jl_printf(out, ":");
1043+
n += jl_static_show_symbol(out, (jl_sym_t*)v);
10111044
}
10121045
else if (vt == jl_ssavalue_type) {
10131046
n += jl_printf(out, "SSAValue(%" PRIuPTR ")",
10141047
(uintptr_t)((jl_ssavalue_t*)v)->id);
10151048
}
10161049
else if (vt == jl_globalref_type) {
10171050
n += jl_static_show_x(out, (jl_value_t*)jl_globalref_mod(v), depth, ctx);
1018-
char *name = jl_symbol_name(jl_globalref_name(v));
1019-
n += jl_printf(out, jl_is_identifier(name) ? ".%s" : ".:(%s)", name);
1051+
jl_sym_t *name = jl_globalref_name(v);
1052+
n += jl_printf(out, ".");
1053+
if (jl_is_operator(jl_symbol_name(name)))
1054+
n += jl_printf(out, ":(%s)", jl_symbol_name(name));
1055+
else
1056+
n += jl_static_show_symbol(out, name);
10201057
}
10211058
else if (vt == jl_gotonode_type) {
10221059
n += jl_printf(out, "goto %" PRIuPTR, jl_gotonode_label(v));
@@ -1050,17 +1087,17 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
10501087
else if (vt == jl_expr_type) {
10511088
jl_expr_t *e = (jl_expr_t*)v;
10521089
if (e->head == jl_assign_sym && jl_array_nrows(e->args) == 2) {
1053-
n += jl_static_show_x(out, jl_exprarg(e,0), depth, ctx);
1090+
n += jl_static_show_x(out, jl_exprarg(e, 0), depth, ctx);
10541091
n += jl_printf(out, " = ");
1055-
n += jl_static_show_x(out, jl_exprarg(e,1), depth, ctx);
1092+
n += jl_static_show_x(out, jl_exprarg(e, 1), depth, ctx);
10561093
}
10571094
else {
1058-
char sep = ' ';
1059-
n += jl_printf(out, "Expr(:%s", jl_symbol_name(e->head));
1095+
n += jl_printf(out, "Expr(");
1096+
n += jl_static_show_x(out, (jl_value_t*)e->head, depth, ctx);
10601097
size_t i, len = jl_array_nrows(e->args);
10611098
for (i = 0; i < len; i++) {
1062-
n += jl_printf(out, ",%c", sep);
1063-
n += jl_static_show_x(out, jl_exprarg(e,i), depth, ctx);
1099+
n += jl_printf(out, ", ");
1100+
n += jl_static_show_x(out, jl_exprarg(e, i), depth, ctx);
10641101
}
10651102
n += jl_printf(out, ")");
10661103
}
@@ -1195,7 +1232,7 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
11951232
}
11961233
}
11971234

1198-
n += jl_static_show_x_sym_escaped(out, sym);
1235+
n += jl_static_show_symbol(out, sym);
11991236

12001237
if (globfunc) {
12011238
if (quote) {
@@ -1231,8 +1268,14 @@ static size_t jl_static_show_x_(JL_STREAM *out, jl_value_t *v, jl_datatype_t *vt
12311268
jl_value_t *names = isnamedtuple ? jl_tparam0(vt) : (jl_value_t*)jl_field_names(vt);
12321269
for (; i < tlen; i++) {
12331270
if (!istuple) {
1234-
jl_value_t *fname = isnamedtuple ? jl_fieldref_noalloc(names, i) : jl_svecref(names, i);
1235-
n += jl_printf(out, "%s=", jl_symbol_name((jl_sym_t*)fname));
1271+
jl_sym_t *fname = (jl_sym_t*)(isnamedtuple ? jl_fieldref_noalloc(names, i) : jl_svecref(names, i));
1272+
if (fname == NULL || !jl_is_symbol(fname))
1273+
n += jl_static_show_x(out, (jl_value_t*)fname, depth, ctx);
1274+
else if (jl_is_operator(jl_symbol_name(fname)))
1275+
n += jl_printf(out, "(%s)", jl_symbol_name(fname));
1276+
else
1277+
n += jl_static_show_symbol(out, fname);
1278+
n += jl_printf(out, "=");
12361279
}
12371280
size_t offs = jl_field_offset(vt, i);
12381281
char *fld_ptr = (char*)v + offs;
@@ -1367,7 +1410,7 @@ size_t jl_static_show_func_sig_(JL_STREAM *s, jl_value_t *type, jl_static_show_c
13671410
if ((jl_nparams(ftype) == 0 || ftype == ((jl_datatype_t*)ftype)->name->wrapper) &&
13681411
((jl_datatype_t*)ftype)->name->mt != jl_type_type_mt &&
13691412
((jl_datatype_t*)ftype)->name->mt != jl_nonfunction_mt) {
1370-
n += jl_printf(s, "%s", jl_symbol_name(((jl_datatype_t*)ftype)->name->mt->name));
1413+
n += jl_static_show_symbol(s, ((jl_datatype_t*)ftype)->name->mt->name);
13711414
}
13721415
else {
13731416
n += jl_printf(s, "(::");
@@ -1466,10 +1509,10 @@ void jl_log(int level, jl_value_t *module, jl_value_t *group, jl_value_t *id,
14661509
}
14671510
jl_printf(str, "\n@ ");
14681511
if (jl_is_string(file)) {
1469-
jl_uv_puts(str, jl_string_data(file), jl_string_len(file));
1512+
jl_static_show_string(str, jl_string_data(file), jl_string_len(file), 0);
14701513
}
14711514
else if (jl_is_symbol(file)) {
1472-
jl_printf(str, "%s", jl_symbol_name((jl_sym_t*)file));
1515+
jl_static_show_string(str, jl_symbol_name((jl_sym_t*)file), strlen(jl_symbol_name((jl_sym_t*)file)), 0);
14731516
}
14741517
jl_printf(str, ":");
14751518
jl_static_show(str, line);

src/support/utf8.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ int u8_escape_wchar(char *buf, size_t sz, uint32_t ch)
410410
}
411411

412412
size_t u8_escape(char *buf, size_t sz, const char *src, size_t *pi, size_t end,
413-
int escape_quotes, int ascii)
413+
const char *escapes, int ascii)
414414
{
415415
size_t i = *pi, i0;
416416
uint32_t ch;
@@ -420,12 +420,9 @@ size_t u8_escape(char *buf, size_t sz, const char *src, size_t *pi, size_t end,
420420

421421
while (i<end && buf<blim) {
422422
// sz-11: leaves room for longest escape sequence
423-
if (escape_quotes && src[i] == '"') {
424-
buf += buf_put2c(buf, "\\\"");
425-
i++;
426-
}
427-
else if (src[i] == '\\') {
428-
buf += buf_put2c(buf, "\\\\");
423+
if ((src[i] == '\\') || (escapes && strchr(escapes, src[i]))) {
424+
*buf++ = '\\';
425+
*buf++ = src[i];
429426
i++;
430427
}
431428
else {
@@ -571,8 +568,8 @@ int u8_isvalid(const char *str, size_t len)
571568
return 0;
572569
// Check for surrogate chars
573570
if (byt == 0xed && *pnt > 0x9f) return 0;
574-
// Check for overlong encoding
575-
if (byt == 0xe0 && *pnt < 0xa0) return 0;
571+
// Check for overlong encoding
572+
if (byt == 0xe0 && *pnt < 0xa0) return 0;
576573
pnt += 2;
577574
} else { // 4-byte sequence
578575
// Must have 3 valid continuation characters

0 commit comments

Comments
 (0)