@@ -206,63 +206,94 @@ defmodule Module.Types.Of do
206
206
In the stack, we add nodes such as <<expr>>, <<..., expr>>, etc,
207
207
based on the position of the expression within the binary.
208
208
"""
209
- def binary ( [ ] , _kind , _stack , context , _of_fun ) do
209
+ def binary ( [ ] , _kind , _stack , context ) do
210
210
{ :ok , context }
211
211
end
212
212
213
- def binary ( [ head ] , kind , stack , context , of_fun ) do
214
- binary_segment ( head , kind , [ head ] , stack , context , of_fun )
213
+ def binary ( [ head ] , kind , stack , context ) do
214
+ binary_segment ( head , kind , [ head ] , stack , context )
215
215
end
216
216
217
- def binary ( [ head | tail ] , kind , stack , context , of_fun ) do
218
- case binary_segment ( head , kind , [ head , @ suffix ] , stack , context , of_fun ) do
219
- { :ok , context } -> binary_many ( tail , kind , stack , context , of_fun )
220
- { :error , reason } -> { :error , reason }
217
+ def binary ( [ head | tail ] , kind , stack , context ) do
218
+ case binary_segment ( head , kind , [ head , @ suffix ] , stack , context ) do
219
+ { :ok , context } -> binary_many ( tail , kind , stack , context )
220
+ { :error , context } -> { :error , context }
221
221
end
222
222
end
223
223
224
- defp binary_many ( [ last ] , kind , stack , context , of_fun ) do
225
- binary_segment ( last , kind , [ @ prefix , last ] , stack , context , of_fun )
224
+ defp binary_many ( [ last ] , kind , stack , context ) do
225
+ binary_segment ( last , kind , [ @ prefix , last ] , stack , context )
226
226
end
227
227
228
- defp binary_many ( [ head | tail ] , kind , stack , context , of_fun ) do
229
- case binary_segment ( head , kind , [ @ prefix , head , @ suffix ] , stack , context , of_fun ) do
230
- { :ok , context } -> binary_many ( tail , kind , stack , context , of_fun )
231
- { :error , reason } -> { :error , reason }
228
+ defp binary_many ( [ head | tail ] , kind , stack , context ) do
229
+ case binary_segment ( head , kind , [ @ prefix , head , @ suffix ] , stack , context ) do
230
+ { :ok , context } -> binary_many ( tail , kind , stack , context )
231
+ { :error , context } -> { :error , context }
232
232
end
233
233
end
234
234
235
235
# If the segment is a literal, the compiler has already checked its validity,
236
236
# so we just skip it.
237
- defp binary_segment ( { :"::" , _meta , [ left , _right ] } , _kind , _args , _stack , context , _of_fun )
237
+ defp binary_segment ( { :"::" , _meta , [ left , _right ] } , _kind , _args , _stack , context )
238
238
when is_binary ( left ) or is_number ( left ) do
239
239
{ :ok , context }
240
240
end
241
241
242
- defp binary_segment ( { :"::" , meta , [ left , right ] } , kind , args , stack , context , of_fun ) do
243
- expected_type = specifier_info ( kind , right )
242
+ defp binary_segment ( { :"::" , meta , [ left , right ] } , kind , args , stack , context ) do
243
+ expected_type = specifier_type ( kind , right )
244
244
expr = { :<<>> , meta , args }
245
245
246
- with { :ok , _type , context } <- of_fun . ( left , { expected_type , expr } , stack , context ) do
247
- { :ok , context }
246
+ result =
247
+ case kind do
248
+ :pattern -> Module.Types.Pattern . of_pattern ( left , { expected_type , expr } , stack , context )
249
+ :guard -> Module.Types.Pattern . of_guard ( left , { expected_type , expr } , stack , context )
250
+ :expr -> Module.Types.Expr . of_expr ( left , { expected_type , expr } , stack , context )
251
+ end
252
+
253
+ with { :ok , _type , context } <- result do
254
+ { :ok , specifier_size ( kind , right , stack , context ) }
255
+ end
256
+ end
257
+
258
+ defp specifier_type ( kind , { :- , _ , [ left , _right ] } ) , do: specifier_type ( kind , left )
259
+ defp specifier_type ( :pattern , { :utf8 , _ , _ } ) , do: @ integer
260
+ defp specifier_type ( :pattern , { :utf16 , _ , _ } ) , do: @ integer
261
+ defp specifier_type ( :pattern , { :utf32 , _ , _ } ) , do: @ integer
262
+ defp specifier_type ( :pattern , { :float , _ , _ } ) , do: @ float
263
+ defp specifier_type ( _kind , { :float , _ , _ } ) , do: @ integer_or_float
264
+ defp specifier_type ( _kind , { :utf8 , _ , _ } ) , do: @ integer_or_binary
265
+ defp specifier_type ( _kind , { :utf16 , _ , _ } ) , do: @ integer_or_binary
266
+ defp specifier_type ( _kind , { :utf32 , _ , _ } ) , do: @ integer_or_binary
267
+ defp specifier_type ( _kind , { :integer , _ , _ } ) , do: @ integer
268
+ defp specifier_type ( _kind , { :bits , _ , _ } ) , do: @ binary
269
+ defp specifier_type ( _kind , { :bitstring , _ , _ } ) , do: @ binary
270
+ defp specifier_type ( _kind , { :bytes , _ , _ } ) , do: @ binary
271
+ defp specifier_type ( _kind , { :binary , _ , _ } ) , do: @ binary
272
+ defp specifier_type ( _kind , _specifier ) , do: @ integer
273
+
274
+ defp specifier_size ( kind , { :- , _ , [ left , right ] } , stack , context ) do
275
+ specifier_size ( kind , right , stack , specifier_size ( kind , left , stack , context ) )
276
+ end
277
+
278
+ defp specifier_size ( :expr , { :size , _ , [ arg ] } = expr , stack , context )
279
+ when not is_integer ( arg ) do
280
+ case Module.Types.Expr . of_expr ( arg , { integer ( ) , expr } , stack , context ) do
281
+ { :ok , _ , context } -> context
282
+ { :error , context } -> context
248
283
end
249
284
end
250
285
251
- defp specifier_info ( kind , { :- , _ , [ left , _right ] } ) , do: specifier_info ( kind , left )
252
- defp specifier_info ( :expr , { :float , _ , _ } ) , do: @ integer_or_float
253
- defp specifier_info ( :expr , { :utf8 , _ , _ } ) , do: @ integer_or_binary
254
- defp specifier_info ( :expr , { :utf16 , _ , _ } ) , do: @ integer_or_binary
255
- defp specifier_info ( :expr , { :utf32 , _ , _ } ) , do: @ integer_or_binary
256
- defp specifier_info ( :pattern , { :utf8 , _ , _ } ) , do: @ integer
257
- defp specifier_info ( :pattern , { :utf16 , _ , _ } ) , do: @ integer
258
- defp specifier_info ( :pattern , { :utf32 , _ , _ } ) , do: @ integer
259
- defp specifier_info ( :pattern , { :float , _ , _ } ) , do: @ float
260
- defp specifier_info ( _kind , { :integer , _ , _ } ) , do: @ integer
261
- defp specifier_info ( _kind , { :bits , _ , _ } ) , do: @ binary
262
- defp specifier_info ( _kind , { :bitstring , _ , _ } ) , do: @ binary
263
- defp specifier_info ( _kind , { :bytes , _ , _ } ) , do: @ binary
264
- defp specifier_info ( _kind , { :binary , _ , _ } ) , do: @ binary
265
- defp specifier_info ( _kind , _specifier ) , do: @ integer
286
+ defp specifier_size ( _pattern_or_guard , { :size , _ , [ arg ] } = expr , stack , context )
287
+ when not is_integer ( arg ) do
288
+ case Module.Types.Pattern . of_guard ( arg , { integer ( ) , expr } , stack , context ) do
289
+ { :ok , _ , context } -> context
290
+ { :error , context } -> context
291
+ end
292
+ end
293
+
294
+ defp specifier_size ( _kind , _expr , _stack , context ) do
295
+ context
296
+ end
266
297
267
298
## Apply
268
299
0 commit comments