@@ -549,30 +549,47 @@ defmodule Module.Types.Of do
549549 In the stack, we add nodes such as <<expr>>, <<..., expr>>, etc,
550550 based on the position of the expression within the binary.
551551 """
552- def bitstring ( [ ] , _kind , _stack , context ) do
553- { binary ( ) , context }
552+ def bitstring ( args , kind , stack , context ) do
553+ { type , nil , context } =
554+ bitstring ( args , kind , stack , context , nil , fn _segment , nil , context ->
555+ { nil , context }
556+ end )
557+
558+ { type , context }
559+ end
560+
561+ def bitstring ( args , kind , stack , context , acc , fun ) when is_function ( fun , 3 ) do
562+ do_bitstring ( args , kind , stack , context , acc , fun )
563+ end
564+
565+ defp do_bitstring ( [ ] , _kind , _stack , context , acc , _fun ) do
566+ { binary ( ) , acc , context }
554567 end
555568
556- def bitstring ( [ head ] , kind , stack , context ) do
557- { alignment , context } = bitstring_segment ( head , kind , [ head ] , stack , context )
558- { alignment_to_type ( alignment ) , context }
569+ defp do_bitstring ( [ head ] , kind , stack , context , acc , fun ) do
570+ { alignment , acc , context } = bitstring_segment ( head , kind , [ head ] , stack , context , acc , fun )
571+ { alignment_to_type ( alignment ) , acc , context }
559572 end
560573
561- def bitstring ( [ head | tail ] , kind , stack , context ) do
562- { alignment , context } = bitstring_segment ( head , kind , [ head , @ suffix ] , stack , context )
563- bitstring_tail ( tail , alignment , kind , stack , context )
574+ defp do_bitstring ( [ head | tail ] , kind , stack , context , acc , fun ) do
575+ { alignment , acc , context } =
576+ bitstring_segment ( head , kind , [ head , @ suffix ] , stack , context , acc , fun )
577+
578+ bitstring_tail ( tail , alignment , kind , stack , context , acc , fun )
564579 end
565580
566- defp bitstring_tail ( [ last ] , alignment , kind , stack , context ) do
567- { seg_alignment , context } = bitstring_segment ( last , kind , [ @ prefix , last ] , stack , context )
568- { alignment_to_type ( alignment ( seg_alignment , alignment ) ) , context }
581+ defp bitstring_tail ( [ last ] , alignment , kind , stack , context , acc , fun ) do
582+ { seg_alignment , acc , context } =
583+ bitstring_segment ( last , kind , [ @ prefix , last ] , stack , context , acc , fun )
584+
585+ { alignment_to_type ( alignment ( seg_alignment , alignment ) ) , acc , context }
569586 end
570587
571- defp bitstring_tail ( [ head | tail ] , alignment , kind , stack , context ) do
572- { seg_alignment , context } =
573- bitstring_segment ( head , kind , [ @ prefix , head , @ suffix ] , stack , context )
588+ defp bitstring_tail ( [ head | tail ] , alignment , kind , stack , context , acc , fun ) do
589+ { seg_alignment , acc , context } =
590+ bitstring_segment ( head , kind , [ @ prefix , head , @ suffix ] , stack , context , acc , fun )
574591
575- bitstring_tail ( tail , alignment ( seg_alignment , alignment ) , kind , stack , context )
592+ bitstring_tail ( tail , alignment ( seg_alignment , alignment ) , kind , stack , context , acc , fun )
576593 end
577594
578595 defp alignment ( left , right ) when is_integer ( left ) and is_integer ( right ) , do: left + right
@@ -582,9 +599,15 @@ defmodule Module.Types.Of do
582599 defp alignment_to_type ( integer ) when rem ( integer , 8 ) == 0 , do: binary ( )
583600 defp alignment_to_type ( _integer ) , do: bitstring_no_binary ( )
584601
602+ defp bitstring_segment ( segment , kind , args , stack , context , acc , fun ) do
603+ { acc , context } = fun . ( segment , acc , context )
604+ { alignment , context } = do_bitstring_segment ( segment , kind , args , stack , context )
605+ { alignment , acc , context }
606+ end
607+
585608 # If the segment is a literal, the compiler has already checked its validity,
586609 # so we just check the size.
587- defp bitstring_segment ( { :"::" , _meta , [ left , right ] } , kind , _args , stack , context )
610+ defp do_bitstring_segment ( { :"::" , _meta , [ left , right ] } , kind , _args , stack , context )
588611 when is_binary ( left ) or is_number ( left ) do
589612 { _type , alignment_type } = specifier_type ( kind , right )
590613 { alignment_value , context } = specifier_size ( kind , right , stack , { :default , context } )
@@ -599,7 +622,7 @@ defmodule Module.Types.Of do
599622 end
600623 end
601624
602- defp bitstring_segment ( { :"::" , meta , [ left , right ] } , kind , args , stack , context ) do
625+ defp do_bitstring_segment ( { :"::" , meta , [ left , right ] } , kind , args , stack , context ) do
603626 { type , alignment_type } = specifier_type ( kind , right )
604627 expr = { :<<>> , meta , args }
605628
0 commit comments