@@ -934,8 +934,8 @@ function operator_associativity(s::Symbol)
934
934
return :left
935
935
end
936
936
937
- is_expr (ex , head:: Symbol ) = ( isa (ex, Expr) && (ex. head == head) )
938
- is_expr (ex , head:: Symbol , n:: Int ) = is_expr (ex, head) && length (ex. args) == n
937
+ is_expr (@nospecialize (ex) , head:: Symbol ) = isa (ex, Expr) && (ex. head === head)
938
+ is_expr (@nospecialize (ex) , head:: Symbol , n:: Int ) = is_expr (ex, head) && length (ex. args) == n
939
939
940
940
is_quoted (ex) = false
941
941
is_quoted (ex:: QuoteNode ) = true
@@ -991,7 +991,8 @@ function show_block(io::IO, head, arg, block, i::Int, quote_level::Int)
991
991
end
992
992
993
993
# show an indented list
994
- function show_list (io:: IO , items, sep, indent:: Int , prec:: Int = 0 , quote_level:: Int = 0 , enclose_operators:: Bool = false )
994
+ function show_list (io:: IO , items, sep, indent:: Int , prec:: Int = 0 , quote_level:: Int = 0 , enclose_operators:: Bool = false ,
995
+ kw:: Bool = false )
995
996
n = length (items)
996
997
n == 0 && return
997
998
indent += indent_width
@@ -1004,20 +1005,27 @@ function show_list(io::IO, items, sep, indent::Int, prec::Int=0, quote_level::In
1004
1005
(item isa Real && item < 0 ))) ||
1005
1006
(enclose_operators && item isa Symbol && isoperator (item))
1006
1007
parens && print (io, ' (' )
1007
- show_unquoted (io, item, indent, parens ? 0 : prec, quote_level)
1008
+ if kw && is_expr (item, :kw , 2 )
1009
+ show_unquoted (io, Expr (:(= ), item. args[1 ], item. args[2 ]), indent, parens ? 0 : prec, quote_level)
1010
+ elseif kw && is_expr (item, :(= ), 2 )
1011
+ show_unquoted_expr_fallback (io, item, indent, quote_level)
1012
+ else
1013
+ show_unquoted (io, item, indent, parens ? 0 : prec, quote_level)
1014
+ end
1008
1015
parens && print (io, ' )' )
1009
1016
first = false
1010
1017
end
1011
1018
end
1012
1019
# show an indented list inside the parens (op, cl)
1013
- function show_enclosed_list (io:: IO , op, items, sep, cl, indent, prec= 0 , quote_level= 0 , encl_ops= false )
1020
+ function show_enclosed_list (io:: IO , op, items, sep, cl, indent, prec= 0 , quote_level= 0 , encl_ops= false , kw :: Bool = false )
1014
1021
print (io, op)
1015
- show_list (io, items, sep, indent, prec, quote_level, encl_ops)
1022
+ show_list (io, items, sep, indent, prec, quote_level, encl_ops, kw )
1016
1023
print (io, cl)
1017
1024
end
1018
1025
1019
1026
# show a normal (non-operator) function call, e.g. f(x, y) or A[z]
1020
- function show_call (io:: IO , head, func, func_args, indent, quote_level)
1027
+ # kw: `=` expressions are parsed with head `kw` in this context
1028
+ function show_call (io:: IO , head, func, func_args, indent, quote_level, kw:: Bool )
1021
1029
op, cl = expr_calls[head]
1022
1030
if (isa (func, Symbol) && func != = :(:) && ! (head === :. && isoperator (func))) ||
1023
1031
(isa (func, Expr) && (func. head === :. || func. head === :curly || func. head === :macroname )) ||
@@ -1033,12 +1041,12 @@ function show_call(io::IO, head, func, func_args, indent, quote_level)
1033
1041
end
1034
1042
if ! isempty (func_args) && isa (func_args[1 ], Expr) && func_args[1 ]. head === :parameters
1035
1043
print (io, op)
1036
- show_list (io, func_args[2 : end ], " , " , indent, 0 , quote_level)
1044
+ show_list (io, func_args[2 : end ], " , " , indent, 0 , quote_level, false , kw )
1037
1045
print (io, " ; " )
1038
- show_list (io, func_args[1 ]. args, " , " , indent, 0 , quote_level)
1046
+ show_list (io, func_args[1 ]. args, " , " , indent, 0 , quote_level, false , kw )
1039
1047
print (io, cl)
1040
1048
else
1041
- show_enclosed_list (io, op, func_args, " , " , cl, indent, 0 , quote_level)
1049
+ show_enclosed_list (io, op, func_args, " , " , cl, indent, 0 , quote_level, false , kw )
1042
1050
end
1043
1051
end
1044
1052
@@ -1147,7 +1155,7 @@ function show_generator(io, ex, indent, quote_level)
1147
1155
end
1148
1156
1149
1157
function valid_import_path (@nospecialize ex)
1150
- return Meta . isexpr (ex, :(.)) && length ((ex:: Expr ). args) > 0 && all (a-> isa (a,Symbol), (ex:: Expr ). args)
1158
+ return is_expr (ex, :(.)) && length ((ex:: Expr ). args) > 0 && all (a-> isa (a,Symbol), (ex:: Expr ). args)
1151
1159
end
1152
1160
1153
1161
function show_import_path (io:: IO , ex, quote_level)
@@ -1194,6 +1202,22 @@ end
1194
1202
# as an ordinary symbol, which is true in indexing expressions.
1195
1203
const beginsym = gensym (:beginsym )
1196
1204
1205
+ function show_unquoted_expr_fallback (io:: IO , ex:: Expr , indent:: Int , quote_level:: Int )
1206
+ print (io, " \$ (Expr(" )
1207
+ show (io, ex. head)
1208
+ for arg in ex. args
1209
+ print (io, " , " )
1210
+ if isa (arg, Expr)
1211
+ print (io, " :(" )
1212
+ show_unquoted (io, arg, indent, 0 , quote_level+ 1 )
1213
+ print (io, " )" )
1214
+ else
1215
+ show (io, arg)
1216
+ end
1217
+ end
1218
+ print (io, " ))" )
1219
+ end
1220
+
1197
1221
# TODO : implement interpolated strings
1198
1222
function show_unquoted (io:: IO , ex:: Expr , indent:: Int , prec:: Int , quote_level:: Int = 0 )
1199
1223
head, args, nargs = ex. head, ex. args, length (ex. args)
@@ -1204,7 +1228,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1204
1228
item = args[1 ]
1205
1229
# field
1206
1230
field = unquoted (args[2 ])
1207
- parens = ! is_quoted (item) && ! (item isa Symbol && isidentifier (item)) && ! Meta . isexpr (item, :(.))
1231
+ parens = ! is_quoted (item) && ! (item isa Symbol && isidentifier (item)) && ! is_expr (item, :(.))
1208
1232
parens && print (io, ' (' )
1209
1233
show_unquoted (io, item, indent, 0 , quote_level)
1210
1234
parens && print (io, ' )' )
@@ -1231,8 +1255,27 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1231
1255
show_list (io, args, head_, indent, func_prec, quote_level, true )
1232
1256
end
1233
1257
1234
- # list (i.e. "(1, 2, 3)" or "[1, 2, 3]")
1235
- elseif haskey (expr_parens, head) || # :tuple/:vcat
1258
+ elseif head === :tuple
1259
+ print (io, " (" )
1260
+ if nargs > 0 && is_expr (args[1 ], :parameters )
1261
+ if nargs == 1 && isempty (args[1 ]. args)
1262
+ # TODO : for now avoid printing (;)
1263
+ show_unquoted_expr_fallback (io, args[1 ], indent, quote_level)
1264
+ print (io, ' ,' )
1265
+ else
1266
+ show_list (io, args[2 : end ], " , " , indent, 0 , quote_level)
1267
+ nargs == 2 && print (io, ' ,' )
1268
+ print (io, " ; " )
1269
+ show_list (io, args[1 ]. args, " , " , indent, 0 , quote_level, false , true )
1270
+ end
1271
+ else
1272
+ show_list (io, args, " , " , indent, 0 , quote_level)
1273
+ nargs == 1 && print (io, ' ,' )
1274
+ end
1275
+ print (io, " )" )
1276
+
1277
+ # list-like forms, e.g. "[1, 2, 3]"
1278
+ elseif haskey (expr_parens, head) || # :vcat etc.
1236
1279
head === :typed_vcat || head === :typed_hcat
1237
1280
# print the type and defer to the untyped case
1238
1281
if head === :typed_vcat || head === :typed_hcat
@@ -1255,12 +1298,8 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1255
1298
end
1256
1299
head != = :row && print (io, op)
1257
1300
show_list (io, args, sep, indent, 0 , quote_level)
1258
- if nargs == 1
1259
- if head === :tuple
1260
- print (io, ' ,' )
1261
- elseif head === :vcat
1262
- print (io, ' ;' )
1263
- end
1301
+ if nargs == 1 && head === :vcat
1302
+ print (io, ' ;' )
1264
1303
end
1265
1304
head != = :row && print (io, cl)
1266
1305
@@ -1274,8 +1313,12 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1274
1313
end
1275
1314
func_args = args[2 : end ]
1276
1315
1316
+ # :kw exprs are only parsed inside parenthesized calls
1317
+ if any (a-> is_expr (a, :kw ), func_args)
1318
+ show_call (io, head, func, func_args, indent, quote_level, true )
1319
+
1277
1320
# scalar multiplication (i.e. "100x")
1278
- if (func === :* &&
1321
+ elseif (func === :* &&
1279
1322
length (func_args)== 2 && isa (func_args[1 ], Real) && isa (func_args[2 ], Symbol))
1280
1323
if func_prec <= prec
1281
1324
show_enclosed_list (io, ' (' , func_args, " " , ' )' , indent, func_prec, quote_level)
@@ -1313,12 +1356,12 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1313
1356
print (io, " )" )
1314
1357
show_enclosed_list (io, op, func_args, " , " , cl, indent, 0 , quote_level)
1315
1358
else
1316
- show_call (io, head, func, func_args, indent, quote_level)
1359
+ show_call (io, head, func, func_args, indent, quote_level, true )
1317
1360
end
1318
1361
1319
1362
# normal function (i.e. "f(x,y)")
1320
1363
else
1321
- show_call (io, head, func, func_args, indent, quote_level)
1364
+ show_call (io, head, func, func_args, indent, quote_level, true )
1322
1365
end
1323
1366
1324
1367
# new expr
@@ -1328,7 +1371,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1328
1371
# other call-like expressions ("A[1,2]", "T{X,Y}", "f.(X,Y)")
1329
1372
elseif haskey (expr_calls, head) && nargs >= 1 # :ref/:curly/:calldecl/:(.)
1330
1373
funcargslike = head === :(.) ? args[2 ]. args : args[2 : end ]
1331
- show_call (head == :ref ? IOContext (io, beginsym=> true ) : io, head, args[1 ], funcargslike, indent, quote_level)
1374
+ show_call (head == :ref ? IOContext (io, beginsym=> true ) : io, head, args[1 ], funcargslike, indent, quote_level, head != = :curly )
1332
1375
1333
1376
# comprehensions
1334
1377
elseif head === :typed_comprehension && nargs == 2
@@ -1386,7 +1429,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1386
1429
1387
1430
# block with argument
1388
1431
elseif head in (:for ,:while ,:function ,:macro ,:if ,:elseif ,:let ) && nargs== 2
1389
- if Meta . isexpr (args[2 ], :block )
1432
+ if is_expr (args[2 ], :block )
1390
1433
show_block (IOContext (io, beginsym=> false ), head, args[1 ], args[2 ], indent, quote_level)
1391
1434
else
1392
1435
show_block (IOContext (io, beginsym=> false ), head, args[1 ], Expr (:block , args[2 ]), indent, quote_level)
@@ -1478,7 +1521,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1478
1521
# prec=-1 and hide the line number argument from the argument list
1479
1522
mname = allow_macroname (args[1 ])
1480
1523
if prec >= 0
1481
- show_call (io, :call , mname, args[3 : end ], indent, quote_level)
1524
+ show_call (io, :call , mname, args[3 : end ], indent, quote_level, false )
1482
1525
else
1483
1526
show_args = Vector {Any} (undef, nargs - 1 )
1484
1527
show_args[1 ] = mname
@@ -1552,7 +1595,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1552
1595
1553
1596
elseif head === :quote && nargs == 1 && isa (args[1 ], Symbol)
1554
1597
show_unquoted_quote_expr (IOContext (io, beginsym=> false ), args[1 ]:: Symbol , indent, 0 , quote_level+ 1 )
1555
- elseif head === :quote && nargs == 1 && Meta . isexpr (args[1 ], :block )
1598
+ elseif head === :quote && nargs == 1 && is_expr (args[1 ], :block )
1556
1599
show_block (IOContext (io, beginsym=> false ), " quote" , Expr (:quote , args[1 ]. args... ), indent,
1557
1600
quote_level+ 1 )
1558
1601
print (io, " end" )
@@ -1576,11 +1619,6 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1576
1619
elseif head === :null
1577
1620
print (io, " nothing" )
1578
1621
1579
- elseif head === :kw && nargs == 2
1580
- show_unquoted (io, args[1 ], indent+ indent_width, 0 , quote_level)
1581
- print (io, ' =' )
1582
- show_unquoted (io, args[2 ], indent+ indent_width, 0 , quote_level)
1583
-
1584
1622
elseif head === :string
1585
1623
print (io, ' "' )
1586
1624
for x in args
@@ -1642,7 +1680,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1642
1680
1643
1681
elseif (head === :import || head === :using ) &&
1644
1682
((nargs == 1 && (valid_import_path (args[1 ]) ||
1645
- (Meta . isexpr (args[1 ], :(:)) &&
1683
+ (is_expr (args[1 ], :(:)) &&
1646
1684
length ((args[1 ]:: Expr ). args) > 1 &&
1647
1685
all (valid_import_path, (args[1 ]:: Expr ). args)))) ||
1648
1686
all (valid_import_path, args))
@@ -1667,19 +1705,7 @@ function show_unquoted(io::IO, ex::Expr, indent::Int, prec::Int, quote_level::In
1667
1705
unhandled = true
1668
1706
end
1669
1707
if unhandled
1670
- print (io, " \$ (Expr(" )
1671
- show (io, ex. head)
1672
- for arg in args
1673
- print (io, " , " )
1674
- if isa (arg, Expr)
1675
- print (io, " :(" )
1676
- show_unquoted (io, arg, indent, 0 , quote_level+ 1 )
1677
- print (io, " )" )
1678
- else
1679
- show (io, arg)
1680
- end
1681
- end
1682
- print (io, " ))" )
1708
+ show_unquoted_expr_fallback (io, ex, indent, quote_level)
1683
1709
end
1684
1710
nothing
1685
1711
end
0 commit comments