@@ -1425,39 +1425,36 @@ if Version.match?(System.version(), ">= 1.17.0-dev") do
1425
1425
end
1426
1426
end
1427
1427
1428
- defp expand_macro ( _meta , Kernel , type , [ { name , _ , params } , [ { _ , block } ] ] , _callback , state , env )
1429
- when type in [ :def , :defp ] and is_tuple ( block ) and is_atom ( name ) and is_list ( params ) do
1430
- { _ , state , penv } =
1431
- for p <- params , reduce: { nil , state , env } do
1432
- { _ , state , penv } ->
1433
- expand_pattern ( p , state , penv )
1428
+ defp expand_macro ( _meta , Kernel , type , args , _callback , state , env )
1429
+ when type in [ :def , :defmacro , :defp , :defmacrop ] do
1430
+ # extract the name, params, guards, and blocks
1431
+ { name , params , guards , blocks } =
1432
+ case args do
1433
+ [ { :when , _ , [ { name , _ , params } | guards ] } | maybe_blocks ] ->
1434
+ { name , params , guards , maybe_blocks }
1435
+
1436
+ [ { name , _ , params } | maybe_blocks ] ->
1437
+ { name , params , [ ] , maybe_blocks }
1434
1438
end
1435
1439
1436
- { res , state , _env } = expand ( block , state , penv )
1437
-
1438
- arity = length ( List . wrap ( params ) )
1439
- functions = Map . update ( state . functions , env . module , [ { name , arity } ] , & Keyword . put_new ( & 1 , name , arity ) )
1440
- { res , put_in ( state . functions , functions ) , env }
1441
- end
1442
-
1443
- defp expand_macro ( _meta , Kernel , type , [ { name , _ , params } , block ] , _callback , state , env )
1444
- when type in [ :defmacro , :defmacrop ] do
1445
- { _res , state , penv } = expand ( params , state , env )
1446
- { res , state , _env } = expand ( block , state , penv )
1440
+ blocks = List . first ( blocks , [ ] )
1447
1441
1448
- arity = length ( List . wrap ( params ) )
1449
- macros = Map . update ( state . macros , env . module , [ { name , arity } ] , & Keyword . put_new ( & 1 , name , arity ) )
1450
- { res , put_in ( state . macros , macros ) , env }
1451
- end
1452
-
1453
- defp expand_macro ( _meta , Kernel , type , [ { name , _ , params } , blocks ] , _callback , state , env )
1454
- when type in [ :def , :defp ] and is_atom ( name ) and is_list ( params ) and is_list ( blocks ) do
1442
+ # collect the environment from the parameters
1443
+ # parameters are always patterns
1455
1444
{ _ , state , penv } =
1456
1445
for p <- params , reduce: { nil , state , env } do
1457
1446
{ _ , state , penv } ->
1458
1447
expand_pattern ( p , state , penv )
1459
1448
end
1460
1449
1450
+ # expand guards, which includes the env from params
1451
+ { _ , state , _ } =
1452
+ for guard <- guards , reduce: { nil , state , penv } do
1453
+ { _ , state , env } ->
1454
+ expand ( guard , state , env )
1455
+ end
1456
+
1457
+ # expand the blocks, there could be `:do`, `:after`, `:catch`, etc
1461
1458
{ blocks , state } =
1462
1459
for { type , block } <- blocks , reduce: { [ ] , state } do
1463
1460
{ acc , state } ->
@@ -1467,26 +1464,21 @@ if Version.match?(System.version(), ">= 1.17.0-dev") do
1467
1464
1468
1465
arity = length ( List . wrap ( params ) )
1469
1466
1470
- functions = Map . update ( state . functions , env . module , [ { name , arity } ] , & Keyword . put_new ( & 1 , name , arity ) )
1471
- { Enum . reverse ( blocks ) , put_in ( state . functions , functions ) , env }
1472
- end
1473
-
1474
- defp expand_macro ( _meta , Kernel , type , [ { _name , _ , params } , blocks ] , _callback , state , env )
1475
- when type in [ :def , :defp ] and is_list ( params ) and is_list ( blocks ) do
1476
- { _ , state , penv } =
1477
- for p <- params , reduce: { nil , state , env } do
1478
- { _ , state , penv } ->
1479
- expand_pattern ( p , state , penv )
1467
+ # determine which key to save this function in state
1468
+ state_key =
1469
+ case type do
1470
+ type when type in [ :def , :defp ] -> :functions
1471
+ type when type in [ :defmacro , :defmacrop ] -> :macros
1480
1472
end
1481
1473
1482
- { blocks , state } =
1483
- for { type , block } <- blocks , reduce: { [ ] , state } do
1484
- { acc , state } ->
1485
- { res , state , _env } = expand ( block , state , penv )
1486
- { [ { type , res } | acc ] , state }
1474
+ funcs =
1475
+ if is_atom ( name ) do
1476
+ Map . update ( state [ state_key ] , env . module , [ { name , arity } ] , & Keyword . put_new ( & 1 , name , arity ) )
1477
+ else
1478
+ state [ state_key ]
1487
1479
end
1488
1480
1489
- { Enum . reverse ( blocks ) , state , env }
1481
+ { Enum . reverse ( blocks ) , put_in ( state [ state_key ] , funcs ) , env }
1490
1482
end
1491
1483
1492
1484
defp expand_macro ( meta , Kernel , :@ , [ { name , _ , p } ] = args , callback , state , env ) when is_list ( p ) do
0 commit comments