@@ -1380,18 +1380,8 @@ function parse_identifier_or_interpolate(ps::ParseState)
1380
1380
end
1381
1381
end
1382
1382
1383
- function finish_macroname (ps, mark, valid_macroname, macro_name_position,
1384
- name_kind= nothing )
1385
- if valid_macroname
1386
- fix_macro_name_kind! (ps, macro_name_position, name_kind)
1387
- else
1388
- emit (ps, mark, K " error" , error= " not a valid macro name or macro module path" )
1389
- end
1390
- end
1391
-
1392
1383
# Parses a chain of sufficies at function call precedence, leftmost binding
1393
1384
# tightest.
1394
- # f(a,b) ==> (call f a b)
1395
1385
# f(a).g(b) ==> (call (. (call f a) (quote g)) b)
1396
1386
#
1397
1387
# flisp: parse-call-chain, parse-call-with-initial-ex
@@ -1404,25 +1394,24 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1404
1394
# source range of the @-prefixed part of a macro
1405
1395
macro_atname_range = nothing
1406
1396
# $A.@x ==> (macrocall (. ($ A) (quote @x)))
1407
- # A.@var"#" ==> (macrocall (. A (quote @x)))
1408
- valid_macroname = peek_behind (ps, skip_trivia= false ). kind in KSet " Identifier var . $"
1397
+ maybe_strmac = true
1409
1398
# We record the last component of chains of dot-separated identifiers so we
1410
1399
# know which identifier was the macro name.
1411
1400
macro_name_position = position (ps) # points to same output span as peek_behind
1412
1401
while true
1413
- this_iter_valid_macroname = false
1402
+ maybe_strmac_1 = false
1414
1403
t = peek_token (ps)
1415
1404
k = kind (t)
1416
1405
if is_macrocall && (preceding_whitespace (t) || is_closing_token (ps, k))
1417
1406
# Macro calls with space-separated arguments
1418
1407
# @foo a b ==> (macrocall @foo a b)
1419
1408
# @foo (x) ==> (macrocall @foo x)
1420
1409
# @foo (x,y) ==> (macrocall @foo (tuple x y))
1421
- # a().@x y ==> (macrocall (error (. (call a) (quote x))) y)
1422
1410
# [@foo x] ==> (vect (macrocall @foo x))
1423
1411
# @var"#" a ==> (macrocall (var @#) a)
1412
+ # A.@x y ==> (macrocall (. A (quote @x)) y)
1424
1413
# A.@var"#" a ==> (macrocall (. A (quote (var @#))) a)
1425
- finish_macroname (ps, mark, valid_macroname , macro_name_position)
1414
+ fix_macro_name_kind! (ps, macro_name_position)
1426
1415
let ps = with_space_sensitive (ps)
1427
1416
# Space separated macro arguments
1428
1417
# A.@foo a b ==> (macrocall (. A (quote @foo)) a b)
@@ -1455,12 +1444,9 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1455
1444
# [f x] ==> (hcat f x)
1456
1445
break
1457
1446
elseif k == K " ("
1458
- if is_macrocall
1459
- # a().@x(y) ==> (macrocall (error (. (call a) (quote x))) y)
1460
- finish_macroname (ps, mark, valid_macroname, macro_name_position)
1461
- end
1462
1447
# f(a,b) ==> (call f a b)
1463
- # f(a; b=1) ==> (call f a (parameters (b 1)))
1448
+ # f(a=1; b=2) ==> (call f (= a 1) (parameters (= b 2)))
1449
+ # f(a; b; c) ==> (call f a (parameters b) (parameters c))
1464
1450
# (a=1)() ==> (call (= a 1))
1465
1451
# f (a) ==> (call f (error-t) a b)
1466
1452
bump_disallowed_space (ps)
@@ -1472,13 +1458,13 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1472
1458
parse_do (ps, mark)
1473
1459
end
1474
1460
if is_macrocall
1475
- break
1461
+ # A.@x(y) ==> (macrocall (. A (quote @x)) y)
1462
+ # A.@x(y).z ==> (. (macrocall (. A (quote @x)) y) (quote z))
1463
+ fix_macro_name_kind! (ps, macro_name_position)
1464
+ is_macrocall = false
1465
+ macro_atname_range = nothing
1476
1466
end
1477
1467
elseif k == K " ["
1478
- if is_macrocall
1479
- # a().@x[1] ==> (macrocall (error (. (call a) (quote x))) (vect 1))
1480
- finish_macroname (ps, mark, valid_macroname, macro_name_position)
1481
- end
1482
1468
m = position (ps)
1483
1469
# a [i] ==> (ref a (error-t) i)
1484
1470
bump_disallowed_space (ps)
@@ -1489,12 +1475,16 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1489
1475
# @S[a,b] ==> (macrocall @S (vect a b))
1490
1476
# @S[a b] ==> (macrocall @S (hcat a b))
1491
1477
# @S[a; b] ==> (macrocall @S (vcat a b))
1478
+ # A.@S[a] ==> (macrocall (. A (quote @S)) (vect a))
1479
+ # @S[a].b ==> (. (macrocall @S (vect a)) (quote b))
1492
1480
# v1.7: @S[a ;; b] ==> (macrocall @S (ncat-2 a b))
1493
1481
# v1.6: @S[a ;; b] ==> (macrocall @S (error (ncat-2 a b)))
1482
+ fix_macro_name_kind! (ps, macro_name_position)
1494
1483
emit (ps, m, ckind, cflags)
1495
1484
check_ncat_compat (ps, m, ckind)
1496
1485
emit (ps, mark, K " macrocall" )
1497
- break
1486
+ is_macrocall = false
1487
+ macro_atname_range = nothing
1498
1488
else
1499
1489
# a[i] ==> (ref a i)
1500
1490
# a[i,j] ==> (ref a i j)
@@ -1516,16 +1506,7 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1516
1506
elseif k == K " ."
1517
1507
# x .y ==> (. x (error-t) (quote y))
1518
1508
bump_disallowed_space (ps)
1519
- if peek (ps, 2 ) == K " '"
1520
- # f.' => f (error-t . ')
1521
- emark = position (ps)
1522
- bump (ps)
1523
- bump (ps)
1524
- emit (ps, emark, K " error" , TRIVIA_FLAG,
1525
- error= " the .' operator for transpose is discontinued" )
1526
- valid_macroname = false
1527
- continue
1528
- end
1509
+ emark = position (ps)
1529
1510
if ! isnothing (macro_atname_range)
1530
1511
# Allow `@` in macrocall only in first and last position
1531
1512
# A.B.@x ==> (macrocall (. (. A (quote B)) (quote @x)))
@@ -1564,21 +1545,20 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1564
1545
elseif k == K " $"
1565
1546
# f.$x ==> (. f (inert ($ x)))
1566
1547
# f.$(x+y) ==> (. f (inert ($ (call + x y))))
1548
+ # A.$B.@x ==> (macrocall (. (. A (inert ($ B))) (quote @x)))
1567
1549
m = position (ps)
1568
1550
bump (ps, TRIVIA_FLAG)
1569
1551
parse_atom (ps)
1570
1552
emit (ps, m, K " $" )
1571
1553
emit (ps, m, K " inert" )
1572
1554
emit (ps, mark, K " ." )
1573
- # A.$B.@x ==> (macrocall (. (. A (inert ($ B))) (quote @x)))
1574
- this_iter_valid_macroname = true
1575
1555
elseif k == K " @"
1576
1556
# A macro call after some prefix A has been consumed
1577
1557
# A.@x ==> (macrocall (. A (quote @x)))
1578
1558
# A.@x a ==> (macrocall (. A (quote @x)) a)
1579
1559
m = position (ps)
1580
1560
if is_macrocall
1581
- # @A.B.@x a ==> (macrocall (error (. A (quote x) )) a)
1561
+ # @A.B.@x a ==> (macrocall (. (. A (quote B)) (quote (error-t) @x )) a)
1582
1562
bump (ps, TRIVIA_FLAG, error= " repeated `@` in macro module path" )
1583
1563
else
1584
1564
bump (ps, TRIVIA_FLAG)
@@ -1589,16 +1569,21 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1589
1569
macro_atname_range = (m, macro_name_position)
1590
1570
emit (ps, m, K " quote" )
1591
1571
emit (ps, mark, K " ." )
1592
- this_iter_valid_macroname = true
1572
+ elseif k == K " '"
1573
+ # TODO : Reclaim dotted postfix operators :-)
1574
+ # f.' => f (error-t ')
1575
+ bump (ps)
1576
+ emit (ps, emark, K " error" , TRIVIA_FLAG,
1577
+ error= " the .' operator for transpose is discontinued" )
1593
1578
else
1594
1579
# Field/property syntax
1595
1580
# f.x.y ==> (. (. f (quote x)) (quote y))
1596
1581
m = position (ps)
1597
1582
parse_atom (ps, false )
1598
1583
macro_name_position = position (ps)
1584
+ maybe_strmac_1 = true
1599
1585
emit (ps, m, K " quote" )
1600
1586
emit (ps, mark, K " ." )
1601
- this_iter_valid_macroname = true
1602
1587
end
1603
1588
elseif k == K " '" && ! preceding_whitespace (t)
1604
1589
# f' ==> (call-post f ')
@@ -1607,27 +1592,28 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1607
1592
emit (ps, mark, K " call" , POSTFIX_OP_FLAG)
1608
1593
elseif k == K " {"
1609
1594
# Type parameter curlies and macro calls
1610
- if is_macrocall
1611
- # a().@x{y} ==> (macrocall (error (. (call a) (quote x))) (braces y))
1612
- finish_macroname (ps, mark, valid_macroname, macro_name_position)
1613
- end
1614
1595
m = position (ps)
1615
1596
# S {a} ==> (curly S (error-t) a)
1616
1597
bump_disallowed_space (ps)
1617
1598
bump (ps, TRIVIA_FLAG)
1618
1599
parse_call_arglist (ps, K " }" )
1619
1600
if is_macrocall
1620
1601
# @S{a,b} ==> (macrocall S (braces a b))
1602
+ # A.@S{a} ==> (macrocall (. A (quote @S)) (braces a))
1603
+ # @S{a}.b ==> (. (macrocall @S (braces a)) (quote b))
1604
+ fix_macro_name_kind! (ps, macro_name_position)
1621
1605
emit (ps, m, K " braces" )
1622
1606
emit (ps, mark, K " macrocall" )
1623
1607
min_supported_version (v " 1.6" , ps, mark, " macro call without space before `{}`" )
1624
- break
1608
+ is_macrocall = false
1609
+ macro_atname_range = nothing
1625
1610
else
1626
1611
# S{a,b} ==> (curly S a b)
1627
1612
emit (ps, mark, K " curly" )
1628
1613
end
1629
1614
elseif k in KSet " \" \"\"\" ` ``` " &&
1630
- ! preceding_whitespace (t) && valid_macroname
1615
+ ! preceding_whitespace (t) &&
1616
+ maybe_strmac && peek_behind (ps, macro_name_position). kind == K " Identifier"
1631
1617
# Custom string and command literals
1632
1618
# x"str" ==> (macrocall @x_str (string-r "str"))
1633
1619
# x`str` ==> (macrocall @x_cmd (cmdstring-r "str"))
@@ -1641,7 +1627,7 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1641
1627
# Use a special token kind for string and cmd macro names so the
1642
1628
# names can be expanded later as necessary.
1643
1629
outk = is_string_delim (k) ? K " StringMacroName" : K " CmdMacroName"
1644
- finish_macroname (ps, mark, valid_macroname , macro_name_position, outk)
1630
+ fix_macro_name_kind! (ps, macro_name_position, outk)
1645
1631
parse_string (ps, true )
1646
1632
t = peek_token (ps)
1647
1633
k = kind (t)
@@ -1660,7 +1646,7 @@ function parse_call_chain(ps::ParseState, mark, is_macrocall=false)
1660
1646
else
1661
1647
break
1662
1648
end
1663
- valid_macroname &= this_iter_valid_macroname
1649
+ maybe_strmac = maybe_strmac_1
1664
1650
end
1665
1651
end
1666
1652
@@ -2267,6 +2253,7 @@ function parse_macro_name(ps::ParseState)
2267
2253
mark = position (ps)
2268
2254
k = peek (ps)
2269
2255
if k == K " ."
2256
+ # TODO : deal with __dot__ lowering in Expr conversion?
2270
2257
# @. y ==> (macrocall @__dot__ y)
2271
2258
bump (ps)
2272
2259
else
0 commit comments