@@ -10,9 +10,9 @@ translate({ '<<>>', Meta, Args } = Original, S) when is_list(Args) ->
10
10
error ->
11
11
case S # elixir_scope .context of
12
12
match ->
13
- build_bitstr (fun elixir_translator :translate_each /2 , Args , Meta , S );
13
+ build_bitstr (fun elixir_translator :translate_each /2 , Args , Meta , nil , S );
14
14
_ ->
15
- { TArgs , { SC , SV } } = build_bitstr (fun elixir_translator :translate_arg /2 , Args , Meta , { S , S }),
15
+ { TArgs , { SC , SV } } = build_bitstr (fun elixir_translator :translate_arg /2 , Args , Meta , nil , { S , S }),
16
16
{ TArgs , umergec (SV , SC ) }
17
17
end ;
18
18
Else -> Else
@@ -75,58 +75,72 @@ translate(Bitstring, S) when is_bitstring(Bitstring) ->
75
75
% * If '::' is given, extract the bitstring information
76
76
% * All the other types are simply translated and handled with Erlang's default
77
77
%
78
- build_bitstr (Fun , Exprs , Meta , S ) ->
79
- { Final , FinalS } = build_bitstr_each (Fun , Exprs , Meta , S , []),
78
+ build_bitstr (Fun , Exprs , Meta , Env , S ) ->
79
+ { Final , FinalS } = build_bitstr_each (Fun , Exprs , Meta , Env , S , []),
80
80
{ { bin , ? line (Meta ), lists :reverse (Final ) }, FinalS }.
81
81
82
- build_bitstr_each (_Fun , [], _Meta , S , Acc ) ->
82
+ build_bitstr_each (_Fun , [], _Meta , _Env , S , Acc ) ->
83
83
{ Acc , S };
84
84
85
- build_bitstr_each (Fun , [{'::' ,_ ,[H ,V ]}|T ], Meta , S , Acc ) ->
85
+ build_bitstr_each (Fun , [{'::' ,_ ,[H ,V ]}|T ], Meta , Env , S , Acc ) ->
86
86
% % Variables defined outside the binary can be accounted
87
87
% % on subparts, however we can't assign new variables.
88
88
case S of
89
89
{ ES , _ } -> []; % % translate_arg, no assigns
90
90
_ -> ES = S # elixir_scope {context = nil } % % translate_each, revert assigns
91
91
end ,
92
92
93
- { Size , Types } = extract_bit_values (Meta , V , ES ),
94
- build_bitstr_each (Fun , T , Meta , S , Acc , H , Size , Types );
93
+ { ExpandedH , ExpandedEnv } = expand (Meta , H , Env , S ),
94
+ { Size , Types } = extract_bit_values (Meta , V , ExpandedEnv , ES ),
95
+ build_bitstr_each (Fun , T , Meta , ExpandedEnv , S , Acc , ExpandedH , Size , Types );
95
96
96
- build_bitstr_each (Fun , [H |T ], Meta , S , Acc ) ->
97
- build_bitstr_each (Fun , T , Meta , S , Acc , H , default , default ).
97
+ build_bitstr_each (Fun , [H |T ], Meta , Env , S , Acc ) ->
98
+ { ExpandedH , ExpandedEnv } = expand (Meta , H , Env , S ),
99
+ build_bitstr_each (Fun , T , Meta , ExpandedEnv , S , Acc , ExpandedH , default , default ).
98
100
99
- build_bitstr_each (Fun , T , Meta , S , Acc , H , Size , Types ) when is_list (H ) ->
101
+ expand (_Meta , H , Env , _S ) when is_integer (H ); is_float (H ); is_atom (H ); is_atom (H ); is_bitstring (H ) ->
102
+ { H , Env };
103
+
104
+ expand (Meta , H , nil , { S , _ }) ->
105
+ expand (Meta , H , elixir_scope :to_ex_env ({ ? line (Meta ), S }), S );
106
+
107
+ expand (Meta , H , nil , S ) ->
108
+ expand (Meta , H , elixir_scope :to_ex_env ({ ? line (Meta ), S }), S );
109
+
110
+ expand (_Meta , H , Env , _S ) ->
111
+ { 'Elixir.Macro' :expand (H , Env ), Env }.
112
+
113
+ build_bitstr_each (Fun , T , Meta , Env , S , Acc , H , Size , Types ) when is_list (H ) ->
100
114
case is_default_or_utf (Types ) of
101
115
true ->
102
116
{ NewAcc , NewS } = lists :foldl (fun (L , { LA , LS }) ->
103
117
{ FL , FS } = Fun (L , LS ),
104
118
{ [{ bin_element , ? line (Meta ), FL , Size , Types }|LA ], FS }
105
119
end , { Acc , S }, H ),
106
- build_bitstr_each (Fun , T , Meta , NewS , NewAcc );
120
+ build_bitstr_each (Fun , T , Meta , Env , NewS , NewAcc );
107
121
false ->
108
- build_bitstr_default (Fun , T , Meta , S , Acc , H , Size , Types )
122
+ build_bitstr_default (Fun , T , Meta , Env , S , Acc , H , Size , Types )
109
123
end ;
110
124
111
- build_bitstr_each (Fun , T , Meta , S , Acc , H , Size , Types ) when is_bitstring (H ) ->
125
+ build_bitstr_each (Fun , T , Meta , Env , S , Acc , H , Size , Types ) when is_bitstring (H ) ->
112
126
case is_default_or_utf (Types ) of
113
127
true ->
114
128
Line = ? line (Meta ),
115
129
{ bin , _ , Elements } = elixir_tree_helpers :elixir_to_erl (H ),
116
130
NewAcc = lists :foldl (fun ({ bin_element , _ , Expr , _ , _ }, FinalAcc ) ->
117
131
[{ bin_element , Line , Expr , Size , Types }|FinalAcc ]
118
132
end , Acc , Elements ),
119
- build_bitstr_each (Fun , T , Meta , S , NewAcc );
133
+ build_bitstr_each (Fun , T , Meta , Env , S , NewAcc );
120
134
false ->
121
- build_bitstr_default (Fun , T , Meta , S , Acc , H , Size , Types )
135
+ build_bitstr_default (Fun , T , Meta , Env , S , Acc , H , Size , Types )
122
136
end ;
123
137
124
- build_bitstr_each (Fun , T , Meta , S , Acc , H , Size , Types ) ->
125
- build_bitstr_default (Fun , T , Meta , S , Acc , H , Size , Types ).
138
+ build_bitstr_each (Fun , T , Meta , Env , S , Acc , H , Size , Types ) ->
139
+ build_bitstr_default (Fun , T , Meta , Env , S , Acc , H , Size , Types ).
126
140
127
- build_bitstr_default (Fun , T , Meta , S , Acc , H , Size , Types ) ->
141
+ build_bitstr_default (Fun , T , Meta , Env , S , Acc , H , Size , Types ) ->
128
142
{ Expr , NS } = Fun (H , S ),
129
- build_bitstr_each (Fun , T , Meta , NS , [{ bin_element , ? line (Meta ), Expr , Size , Types }|Acc ]).
143
+ build_bitstr_each (Fun , T , Meta , Env , NS , [{ bin_element , ? line (Meta ), Expr , Size , Types }|Acc ]).
130
144
131
145
is_default_or_utf (default ) -> true ;
132
146
is_default_or_utf ([UTF |_ ]) when UTF == utf8 ; UTF == utf16 ; UTF == utf32 -> true ;
@@ -135,46 +149,46 @@ is_default_or_utf([]) -> false.
135
149
136
150
% % Extra bitstring specifiers
137
151
138
- extract_bit_values (Meta , V , S ) when is_list (V ) ->
139
- extract_bit_values (Meta , V , default , [], S );
152
+ extract_bit_values (Meta , V , Env , S ) when is_list (V ) ->
153
+ extract_bit_values (Meta , V , default , [], Env , S );
140
154
141
- extract_bit_values (Meta , V , S ) ->
142
- extract_bit_values (Meta , [V ], S ).
155
+ extract_bit_values (Meta , V , Env , S ) ->
156
+ extract_bit_values (Meta , [V ], Env , S ).
143
157
144
- extract_bit_values (Meta , [{ Value , _Meta , Atom }|T ] = All , Size , Types , S )
158
+ extract_bit_values (Meta , [{ Value , _Meta , Atom }|T ] = All , Size , Types , Env , S )
145
159
when is_atom (Value ) andalso (is_atom (Atom ) orelse Atom == []) ->
146
160
case extract_bit_type (Value , Types ) of
147
161
{ error , unknown } ->
148
- handle_unknown_specifier (Meta , All , Size , Types , S );
162
+ handle_unknown_specifier (Meta , All , Size , Types , Env , S );
149
163
NewTypes when is_list (NewTypes ) ->
150
- extract_bit_values (Meta , T , Size , NewTypes , S )
164
+ extract_bit_values (Meta , T , Size , NewTypes , Env , S )
151
165
end ;
152
166
153
- extract_bit_values (Meta , [{ Value , CallMeta , [_ ] = Args }|T ] = All , Size , Types , S ) when is_atom (Value ) ->
167
+ extract_bit_values (Meta , [{ Value , CallMeta , [_ ] = Args }|T ] = All , Size , Types , Env , S ) when is_atom (Value ) ->
154
168
{ TArgs , _ } = elixir_translator :translate_args (Args , S ),
155
169
case extract_bit_type_or_size (Value , TArgs , Size , Types ) of
156
170
{ error , unknown } ->
157
- handle_unknown_specifier (Meta , All , Size , Types , S );
171
+ handle_unknown_specifier (Meta , All , Size , Types , Env , S );
158
172
{ error , Msg } ->
159
173
elixir_errors :syntax_error (CallMeta , S # elixir_scope .file , Msg );
160
174
{ NewSize , NewTypes } ->
161
- extract_bit_values (Meta , T , NewSize , NewTypes , S )
175
+ extract_bit_values (Meta , T , NewSize , NewTypes , Env , S )
162
176
end ;
163
177
164
- extract_bit_values (Meta , [Size |T ], default , Types , S ) when is_integer (Size ) andalso Size >= 0 ->
165
- extract_bit_values (Meta , T , {integer , Meta , Size }, Types , S );
178
+ extract_bit_values (Meta , [Size |T ], default , Types , Env , S ) when is_integer (Size ) andalso Size >= 0 ->
179
+ extract_bit_values (Meta , T , {integer , Meta , Size }, Types , Env , S );
166
180
167
- extract_bit_values (Meta , [{ '|' , _ , [Left , Right ] }], Size , Types , S ) ->
168
- Expanded = 'Elixir.Macro' : expand (Right , elixir_scope : to_ex_env ({ ? line ( Meta ) , S }) ),
169
- extract_bit_values (Meta , [Left |join_expansion (Expanded ,[])], Size , Types , S );
181
+ extract_bit_values (Meta , [{ '|' , _ , [Left , Right ] }], Size , Types , Env , S ) ->
182
+ { Expanded , ExpandedEnv } = expand (Meta , Right , Env , S ),
183
+ extract_bit_values (Meta , [Left |join_expansion (Expanded ,[])], Size , Types , ExpandedEnv , S );
170
184
171
- extract_bit_values (Meta , [_ |_ ] = All , Size , Types , S ) ->
172
- handle_unknown_specifier (Meta , All , Size , Types , S );
185
+ extract_bit_values (Meta , [_ |_ ] = All , Size , Types , Env , S ) ->
186
+ handle_unknown_specifier (Meta , All , Size , Types , Env , S );
173
187
174
- extract_bit_values (_Meta , [], Size , [], _S ) ->
188
+ extract_bit_values (_Meta , [], Size , [], _Env , _S ) ->
175
189
{ Size , default };
176
190
177
- extract_bit_values (_Meta , [], Size , Types , _S ) ->
191
+ extract_bit_values (_Meta , [], Size , Types , _Env , _S ) ->
178
192
{ Size , lists :reverse (Types ) }.
179
193
180
194
extract_bit_type (Value , Types ) when
@@ -206,12 +220,12 @@ extract_bit_type_or_size(unit, _Args, _Other, _Types) ->
206
220
extract_bit_type_or_size (_Value , _Args , _Other , _Types ) ->
207
221
{ error , unknown }.
208
222
209
- handle_unknown_specifier (Meta , [H |T ], Size , Types , S ) ->
210
- case 'Elixir.Macro' : expand (H , elixir_scope : to_ex_env ({ ? line ( Meta ) , S }) ) of
211
- H ->
223
+ handle_unknown_specifier (Meta , [H |T ], Size , Types , Env , S ) ->
224
+ case expand (Meta , H , Env , S ) of
225
+ { H , _ } ->
212
226
elixir_errors :syntax_error (Meta , S # elixir_scope .file , " unknown bitstring specifier ~ts " , ['Elixir.Macro' :to_binary (H )]);
213
- E ->
214
- extract_bit_values (Meta , join_expansion (E ,T ), Size , Types , S )
227
+ { E , ExpandedEnv } ->
228
+ extract_bit_values (Meta , join_expansion (E ,T ), Size , Types , ExpandedEnv , S )
215
229
end .
216
230
217
231
join_expansion ({ '__block__' , _ , [Expanded ] }, Tail ) -> join_expansion (Expanded , Tail );
0 commit comments