11
11
%%% In matching we convert to bit lists only as much as we
12
12
%%% need, and keep the tail as a binary.
14
%%% expr_grp/5 returns {value, Binary, New_bindings}.
15
%%% match_bits/6 returns either {match, New_bindings} or 'nomatch',
16
%%% or throws 'invalid' (if a pattern is illegal - this can only happen
17
%%% if lint hasn't been run).
14
%%% expr_grp/5 returns {value, Binary, New_bindings} or exits with
15
%%% {Reason,[{erl_eval,expr,3}]} (any other reply is a bug).
16
%%% match_bits/6 returns either {match, New_bindings} or throws one of
17
%%% 'nomatch' or 'invalid' (the latter if a pattern is illegal - this
18
%%% can only happen if lint hasn't been run).
18
19
%%% Their last argument should be 'true' if type defaulting should be
19
20
%%% done, 'false' otherwise (e.g., if sys_pre_expand has already done it).
21
%%% However, it works to always use 'true' for the last argument, so
22
%%% this argument is could actually be removed.
22
24
%% error(Reason) -> exception thrown
23
25
%% Throw a nice-looking exception, similar to exceptions from erl_eval.
64
66
expr_bit({bin_element, _, {string, _, S}, default, default}, Bs0, _Fun,
66
68
{bytes_to_bits(S), Bs0};
67
expr_bit({bin_element, Line, E, Size0, Options0}, Bs0, Fun, Call_maketype) ->
68
format("bit expr ~w~n", [{bin_element, Line, E, Size0, Options0}]),
69
expr_bit({bin_element, _Line, E, Size0, Options0}, Bs0, Fun, Call_maketype) ->
70
%%format("bit expr ~w~n", [{bin_element, _Line, E, Size0, Options0}]),
69
71
{value, V, Bs1} = Fun(E, Bs0),
70
72
{Size1, Options} = maketype(Size0, Options0, Call_maketype),
71
73
{value, Size, Bs} = Fun(Size1, Bs1),
72
format("bit expr ~w~n", [{bin_element, x, V, Size, Options}]),
74
%%format("bit expr ~w~n", [{bin_element, x, V, Size, Options}]),
73
75
Bitl = to_binary(V, Size, Options),
74
format("bit list ~w~n", [Bitl]),
76
%%format("bit list ~w~n", [Bitl]),
77
79
size_or_all(all, All) -> All;
78
size_or_all(N, _All) -> N.
80
size_or_all(N, _All) when N >= 0 -> N;
81
size_or_all(_N, _All) -> error(badarg).
80
83
to_binary(B0, Size0, [binary,{unit,Unit}|_]) when is_binary(B0) ->
81
84
Size1 = size_or_all(Size0, size(B0)),
82
85
binary_to_bits(B0, Size1*Unit);
83
to_binary(I, Size0, [integer,{unit,Unit}|Opts]) when is_integer(I) ->
86
to_binary(I, Size0, [integer,{unit,Unit}|Opts]) when is_integer(Size0),
85
90
L = i_to_bytes(I, Size),
86
91
Bits = binary_to_bits(list_to_binary(L), Size),
87
92
to_little_endian(Bits, Opts);
88
to_binary(F, Size0, [float,{unit,Unit}|Opts]) when is_float(F) ->
93
to_binary(F, Size0, [float,{unit,Unit}|Opts]) when is_integer(Size0),
90
98
Bits = float_to_ieee(F, Size),
91
99
to_little_endian(Bits, Opts);
100
to_binary(_, _Size0, _Options) ->
95
103
type_and_unit([Type,{unit,Unit}|_]) -> {Type,Unit}.
170
178
make_bit_type(Line, default, Type0) ->
171
179
case erl_bits:set_bit_type(default, Type0) of
172
180
{ok,all,Bt} -> {{atom,Line,all},erl_bits:as_list(Bt)};
173
{ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)}
181
{ok,Size,Bt} -> {{integer,Line,Size},erl_bits:as_list(Bt)};
182
{error,Reason} -> error(Reason)
175
make_bit_type(_Line, Size, Type0) -> %Integer or 'all'
176
{ok,Size,Bt} = erl_bits:set_bit_type(Size, Type0),
177
{Size,erl_bits:as_list(Bt)}.
184
make_bit_type(_Line, Size, Type0) -> %Size evaluates to an integer or 'all'
185
case erl_bits:set_bit_type(Size, Type0) of
186
{ok,Size,Bt} -> {Size,erl_bits:as_list(Bt)};
187
{error,Reason} -> error(Reason)
179
190
%%% Part 2: matching
204
215
Tail = foldl(fun(C, <<C:8,Tail/binary>>) -> Tail;
206
217
{Bits,Tail} = get_bits(Bits0, 8),
207
C = bits_to_bytes(Bits),
218
[C] = bits_to_bytes(Bits),
211
match_field({bin_element,_,E,default,[binary|_]}, Bin, Bs0, BBs,
213
{match,Bs} = Mfun(E, Bin, Bs0),
215
match_field({bin_element, _,E,Size0,Options0}, Bin, Bs0, BBs, Mfun, Efun,
222
match_field({bin_element,L,E,default,[binary|_]=Opts}, Bin, Bs0, BBs,
223
Mfun, Efun, Call_maketype) ->
224
match_field({bin_element,L,E,{atom,L,all},Opts}, Bin, Bs0, BBs, Mfun,
225
Efun, Call_maketype);
226
match_field({bin_element, _,E0,Size0,Options0}, Bin, Bs0, BBs, Mfun, Efun,
216
227
Call_maketype) ->
217
228
{Size1,Options} = maketype(Size0, Options0, Call_maketype),
229
E = coerce_to_float(E0,Options),
218
230
match_check_size(Size1, BBs),
219
231
case Efun(Size1, BBs) of
220
232
{value,all,_} when binary(Bin) ->
221
233
{match,Bs} = Mfun(E, Bin, Bs0),
223
235
{Bs,add_bin_binding(E, Val, BBs),Val};
236
{value,Size,_} when Size >= 0 ->
225
237
{Type,Unit} = type_and_unit(Options),
226
238
{Val,Tail} = match_thing(Type, Options, Size*Unit, Bin),
227
239
{match,Bs} = Mfun(E, Val, Bs0),
228
240
{Bs,add_bin_binding(E, Val, BBs),Tail}
243
%% Identical to the one in sys_pre_expand.
244
coerce_to_float({integer,L,I}=E, [float|_]) ->
251
coerce_to_float(E, _) -> E.
231
253
add_bin_binding({var,_,Var}, Val, BBs) ->
232
254
erl_eval:add_binding(Var, Val, BBs);
233
255
add_bin_binding(_, _, BBs) -> BBs.
246
268
Bits1 = from_little_endian(Bits0, Opts),
247
269
<<Float:Size/float>> = list_to_binary(bits_to_bytes(Bits1)),
249
match_thing(Type, Opts, Size, Bin) ->
250
erlang:display({Type,Opts,Size,Bin}),
271
match_thing(_Type, _Opts, _Size, _Bin) ->
272
%%erlang:display({_Type,_Opts,_Size,_Bin}), "cannot happen"
253
275
match_check_size({var,_,V}, Bs) ->