Also, I’ve noticed something after refactoring to inline case statement:
This generates almost 150k cases, it compiles fast and runtime is great almost 2.5x faster then a guard version, although if I change the return to a function, then everything blows up
case_ast =
for c <- Unicode.Set.to_pattern!("[[:Lu:], [:Ll:], [:Lt:], [:Lm:], [:Lo:], [:Nl:], [:Mn:], [:Mc:], [:Nd:], [:Pc:], [:Cf:]]") do
hd(
quote do
<<unquote(c), _::binary>> -> true
end
)
end ++ quote do
_ -> false
end
def case_fn(binary) do
case binary do
unquote(case_ast)
end
end
sql git:(main) ✗ mix sql.bench
Operating System: macOS
CPU Information: Apple M1 Max
Number of Available Cores: 10
Available memory: 64 GB
Elixir 1.20.0-dev
Erlang 28.1
JIT enabled: true
Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 2 s
reduction time: 2 s
parallel: 1
inputs: 1..100_000
Estimated total run time: 22 s
Measured function call overhead as: 0 ns
Benchmarking case with input 1..100_000 ...
Benchmarking guard with input 1..100_000 ...
Calculating statistics...
Formatting results...
##### With input 1..100_000 #####
Name ips average deviation median 99th %
case 15.07 M 66.35 ns ±42238.21% 42 ns 42 ns
guard 6.14 M 162.76 ns ±15740.33% 125 ns 167 ns
Comparison:
case 15.07 M
guard 6.14 M - 2.45x slower +96.41 ns
Memory usage statistics:
Name Memory usage
case 40 B
guard 40 B - 1.00x memory usage +0 B
**All measurements for memory usage were the same**
Reduction count statistics:
Name Reduction count
case 2
guard 2 - 1.00x reduction count +0
Compiling lib/lexer.ex (it's taking more than 10s)
Compiling /Users/benjaminschultzer/src/sql/lib/lexer.ex
get_module_name_from_core : 0.000 s 1567585.5 kB
core_lint_module : 0.178 s 1567585.8 kB
core_compile_directives : 0.000 s 1567585.9 kB
sys_core_fold : 1.161 s 1573464.2 kB
sys_core_alias : 0.303 s 1573464.2 kB
core_transforms : 0.000 s 1573464.2 kB
sys_core_bsm : 0.158 s 1573464.2 kB
core_to_ssa : 2.666 s 860694.9 kB
beam_ssa_bool : 4.381 s 851660.4 kB
beam_ssa_share : 1.505 s 851494.1 kB
beam_ssa_recv : 0.012 s 851494.1 kB
beam_ssa_bsm : 24.190 s 863380.4 kB
%% Sub passes of beam_ssa_bsm from slowest to fastest:
combine_matches : 10.507 s 43 %
skip_outgoing_tail_extracti: 6.934 s 29 %
accept_context_args : 4.348 s 18 %
allow_context_passthrough : 2.392 s 10 %
annotate_context_parameters: 0.000 s 0 %
beam_ssa_opt : 99.483 s 1047863.4 kB
%% Sub passes of beam_ssa_opt from slowest to fastest:
ssa_opt_type_start : 43.199 s 44 %
ssa_opt_alias : 12.884 s 13 %
ssa_opt_live : 9.043 s 9 %
ssa_opt_dead : 6.087 s 6 %
ssa_opt_type_continue : 5.636 s 6 %
ssa_opt_bsm_shortcut : 3.546 s 4 %
ssa_opt_cse : 3.431 s 3 %
ssa_opt_ranges : 1.818 s 2 %
ssa_opt_try : 1.559 s 2 %
ssa_opt_trim_unreachable : 1.284 s 1 %
ssa_opt_merge_blocks : 1.233 s 1 %
ssa_opt_linearize : 1.028 s 1 %
ssa_opt_tail_phis : 0.972 s 1 %
ssa_opt_element : 0.958 s 1 %
ssa_opt_bs_ensure : 0.946 s 1 %
ssa_opt_tail_literals : 0.833 s 1 %
ssa_opt_float : 0.719 s 1 %
ssa_opt_split_blocks : 0.692 s 1 %
ssa_opt_coalesce_phis : 0.570 s 1 %
ssa_opt_redundant_br : 0.561 s 1 %
ssa_opt_record : 0.361 s 0 %
ssa_opt_update_tuple : 0.187 s 0 %
ssa_opt_bsm : 0.165 s 0 %
ssa_opt_no_reuse : 0.109 s 0 %
ssa_opt_blockify : 0.078 s 0 %
ssa_opt_ne : 0.077 s 0 %
ssa_opt_tuple_size : 0.061 s 0 %
ssa_opt_get_tuple_element : 0.055 s 0 %
ssa_opt_type_finish : 0.053 s 0 %
ssa_opt_sink : 0.044 s 0 %
ssa_opt_bs_create_bin : 0.043 s 0 %
ssa_opt_destructive_update : 0.016 s 0 %
ssa_opt_bc_size : 0.012 s 0 %
ssa_opt_sw : 0.011 s 0 %
ssa_opt_merge_updates : 0.009 s 0 %
ssa_opt_unfold_literals : 0.000 s 0 %
beam_ssa_throw : 2.323 s 1047863.4 kB
beam_ssa_pre_codegen : 20.689 s 1036708.9 kB
%% Sub passes of beam_ssa_pre_codegen from slowest to fastest:
fix_bs : 4.854 s 24 %
live_intervals : 3.679 s 18 %
reserve_regs : 2.682 s 13 %
sanitize : 2.137 s 10 %
place_frames : 1.730 s 8 %
number_instructions : 1.486 s 7 %
assert_no_critical_edges : 1.218 s 6 %
linear_scan : 1.089 s 5 %
expand_update_tuple : 1.049 s 5 %
opt_get_list : 0.647 s 3 %
expand_match_fail : 0.023 s 0 %
find_yregs : 0.021 s 0 %
fix_receives : 0.012 s 0 %
reserve_yregs : 0.004 s 0 %
turn_yregs : 0.003 s 0 %
frame_size : 0.002 s 0 %
copy_retval : 0.001 s 0 %
beam_ssa_codegen : 7.125 s 702342.0 kB
beam_validator_strong : 1.898 s 702342.0 kB
beam_a : 0.122 s 704474.8 kB
beam_block : 0.164 s 763859.5 kB
beam_jump : 1.409 s 735968.3 kB
beam_clean : 0.081 s 735968.3 kB
beam_trim : 0.016 s 735993.6 kB
beam_flatten : 0.049 s 676610.4 kB
beam_z : 0.036 s 668886.5 kB
beam_validator_weak : 2.062 s 668886.5 kB
beam_asm : 1.794 s 478814.8 kB
Compiling /Users/benjaminschultzer/src/sql/lib/mix/tasks/sql.get.ex
get_module_name_from_core : 0.000 s 473.2 kB
core_lint_module : 0.000 s 473.7 kB
core_compile_directives : 0.000 s 473.7 kB
sys_core_fold : 0.000 s 432.9 kB
sys_core_alias : 0.000 s 432.9 kB
core_transforms : 0.000 s 432.9 kB
sys_core_bsm : 0.000 s 432.9 kB
core_to_ssa : 0.000 s 248.7 kB
beam_ssa_bool : 0.000 s 243.0 kB
beam_ssa_share : 0.000 s 241.4 kB
beam_ssa_recv : 0.000 s 241.4 kB
beam_ssa_bsm : 0.000 s 241.8 kB
%% Sub passes of beam_ssa_bsm from slowest to fastest:
allow_context_passthrough : 0.000 s 93 %
combine_matches : 0.000 s 2 %
annotate_context_parameters: 0.000 s 2 %
accept_context_args : 0.000 s 1 %
skip_outgoing_tail_extracti: 0.000 s 1 %
beam_ssa_opt : 0.005 s 310.2 kB
%% Sub passes of beam_ssa_opt from slowest to fastest:
ssa_opt_type_start : 0.001 s 31 %
ssa_opt_type_continue : 0.001 s 27 %
ssa_opt_alias : 0.001 s 12 %
ssa_opt_live : 0.000 s 9 %
ssa_opt_dead : 0.000 s 8 %
ssa_opt_cse : 0.000 s 4 %
ssa_opt_sink : 0.000 s 2 %
ssa_opt_float : 0.000 s 1 %
ssa_opt_tail_phis : 0.000 s 1 %
ssa_opt_merge_blocks : 0.000 s 1 %
ssa_opt_try : 0.000 s 1 %
ssa_opt_linearize : 0.000 s 1 %
ssa_opt_coalesce_phis : 0.000 s 1 %
ssa_opt_unfold_literals : 0.000 s 0 %
ssa_opt_trim_unreachable : 0.000 s 0 %
ssa_opt_ranges : 0.000 s 0 %
ssa_opt_destructive_update : 0.000 s 0 %
ssa_opt_merge_updates : 0.000 s 0 %
ssa_opt_element : 0.000 s 0 %
ssa_opt_split_blocks : 0.000 s 0 %
ssa_opt_redundant_br : 0.000 s 0 %
ssa_opt_record : 0.000 s 0 %
ssa_opt_tail_literals : 0.000 s 0 %
ssa_opt_bs_ensure : 0.000 s 0 %
ssa_opt_update_tuple : 0.000 s 0 %
ssa_opt_bs_create_bin : 0.000 s 0 %
ssa_opt_no_reuse : 0.000 s 0 %
ssa_opt_tuple_size : 0.000 s 0 %
ssa_opt_bsm : 0.000 s 0 %
ssa_opt_ne : 0.000 s 0 %
ssa_opt_bc_size : 0.000 s 0 %
ssa_opt_blockify : 0.000 s 0 %
ssa_opt_get_tuple_element : 0.000 s 0 %
ssa_opt_bsm_shortcut : 0.000 s 0 %
ssa_opt_sw : 0.000 s 0 %
ssa_opt_type_finish : 0.000 s 0 %
beam_ssa_throw : 0.000 s 310.2 kB
beam_ssa_pre_codegen : 0.001 s 323.6 kB
%% Sub passes of beam_ssa_pre_codegen from slowest to fastest:
live_intervals : 0.000 s 20 %
linear_scan : 0.000 s 13 %
place_frames : 0.000 s 12 %
reserve_regs : 0.000 s 12 %
reserve_yregs : 0.000 s 9 %
find_yregs : 0.000 s 8 %
frame_size : 0.000 s 5 %
turn_yregs : 0.000 s 4 %
sanitize : 0.000 s 4 %
assert_no_critical_edges : 0.000 s 2 %
expand_update_tuple : 0.000 s 2 %
number_instructions : 0.000 s 2 %
copy_retval : 0.000 s 2 %
fix_bs : 0.000 s 1 %
fix_receives : 0.000 s 1 %
opt_get_list : 0.000 s 1 %
expand_match_fail : 0.000 s 0 %
beam_ssa_codegen : 0.000 s 202.1 kB
beam_validator_strong : 0.000 s 202.1 kB
beam_a : 0.000 s 201.7 kB
beam_block : 0.000 s 207.0 kB
beam_jump : 0.000 s 206.8 kB
beam_clean : 0.000 s 206.9 kB
beam_trim : 0.000 s 206.7 kB
beam_flatten : 0.000 s 200.5 kB
beam_z : 0.000 s 189.4 kB
beam_validator_weak : 0.000 s 189.4 kB
beam_asm : 0.001 s 132.6 kB
Compiling /Users/benjaminschultzer/src/sql/lib/lexer.ex
get_module_name_from_core : 0.000 s 1567585.5 kB
core_lint_module : 0.179 s 1567585.8 kB
core_compile_directives : 0.000 s 1567585.9 kB
sys_core_fold : 1.129 s 1573464.2 kB
sys_core_alias : 0.302 s 1573464.2 kB
core_transforms : 0.000 s 1573464.2 kB
sys_core_bsm : 0.257 s 1573464.2 kB
core_to_ssa : 2.865 s 860694.9 kB
beam_ssa_bool : 3.936 s 851660.4 kB
beam_ssa_share : 1.484 s 851494.1 kB
beam_ssa_recv : 0.014 s 851494.1 kB
beam_ssa_bsm : 24.808 s 863380.4 kB
%% Sub passes of beam_ssa_bsm from slowest to fastest:
combine_matches : 10.964 s 44 %
skip_outgoing_tail_extracti: 7.198 s 29 %
accept_context_args : 4.480 s 18 %
allow_context_passthrough : 2.154 s 9 %
annotate_context_parameters: 0.000 s 0 %
beam_ssa_opt : 102.630 s 1047863.4 kB
%% Sub passes of beam_ssa_opt from slowest to fastest:
ssa_opt_type_start : 45.082 s 44 %
ssa_opt_alias : 14.295 s 14 %
ssa_opt_live : 9.553 s 9 %
ssa_opt_dead : 5.745 s 6 %
ssa_opt_type_continue : 5.058 s 5 %
ssa_opt_bsm_shortcut : 4.023 s 4 %
ssa_opt_cse : 3.329 s 3 %
ssa_opt_ranges : 1.894 s 2 %
ssa_opt_try : 1.759 s 2 %
ssa_opt_trim_unreachable : 1.208 s 1 %
ssa_opt_merge_blocks : 1.195 s 1 %
ssa_opt_bs_ensure : 1.001 s 1 %
ssa_opt_linearize : 0.951 s 1 %
ssa_opt_element : 0.912 s 1 %
ssa_opt_tail_phis : 0.885 s 1 %
ssa_opt_tail_literals : 0.812 s 1 %
ssa_opt_float : 0.706 s 1 %
ssa_opt_redundant_br : 0.634 s 1 %
ssa_opt_split_blocks : 0.632 s 1 %
ssa_opt_coalesce_phis : 0.520 s 1 %
ssa_opt_record : 0.345 s 0 %
ssa_opt_update_tuple : 0.173 s 0 %
ssa_opt_bsm : 0.150 s 0 %
ssa_opt_ne : 0.132 s 0 %
ssa_opt_no_reuse : 0.088 s 0 %
ssa_opt_blockify : 0.081 s 0 %
ssa_opt_get_tuple_element : 0.058 s 0 %
ssa_opt_type_finish : 0.055 s 0 %
ssa_opt_tuple_size : 0.053 s 0 %
ssa_opt_sink : 0.046 s 0 %
ssa_opt_bs_create_bin : 0.043 s 0 %
ssa_opt_destructive_update : 0.014 s 0 %
ssa_opt_bc_size : 0.012 s 0 %
ssa_opt_merge_updates : 0.011 s 0 %
ssa_opt_sw : 0.010 s 0 %
ssa_opt_unfold_literals : 0.000 s 0 %
beam_ssa_throw : 2.316 s 1047863.4 kB
beam_ssa_pre_codegen : 21.428 s 1036708.9 kB
%% Sub passes of beam_ssa_pre_codegen from slowest to fastest:
fix_bs : 4.609 s 22 %
live_intervals : 4.025 s 19 %
reserve_regs : 2.829 s 13 %
sanitize : 2.361 s 11 %
place_frames : 1.683 s 8 %
number_instructions : 1.459 s 7 %
expand_update_tuple : 1.276 s 6 %
assert_no_critical_edges : 1.221 s 6 %
linear_scan : 1.188 s 6 %
opt_get_list : 0.661 s 3 %
expand_match_fail : 0.031 s 0 %
find_yregs : 0.019 s 0 %
fix_receives : 0.013 s 0 %
reserve_yregs : 0.004 s 0 %
turn_yregs : 0.002 s 0 %
frame_size : 0.002 s 0 %
copy_retval : 0.001 s 0 %
beam_ssa_codegen : 6.595 s 702342.0 kB
beam_validator_strong : 2.608 s 702342.0 kB
beam_a : 0.311 s 704474.8 kB
beam_block : 0.346 s 763859.5 kB
beam_jump : 1.486 s 735968.3 kB
beam_clean : 0.154 s 735968.3 kB
beam_trim : 0.011 s 735993.6 kB
beam_flatten : 0.082 s 676610.4 kB
beam_z : 0.103 s 668886.5 kB
beam_validator_weak : 2.331 s 668886.5 kB
beam_asm : 1.832 s 478814.8 kB
defp lex(rest, context, line, column, acc) do
case rest do
<<226, 129, 166, _::binary>> -> {:error, :bidi, line, column}
<<226, 129, 167, _::binary>> -> {:error, :bidi, line, column}
<<226, 129, 168, _::binary>> -> {:error, :bidi, line, column}
<<226, 129, 169, _::binary>> -> {:error, :bidi, line, column}
<<226, 128, 170, _::binary>> -> {:error, :bidi, line, column}
<<226, 128, 171, _::binary>> -> {:error, :bidi, line, column}
<<226, 128, 172, _::binary>> -> {:error, :bidi, line, column}
<<226, 128, 173, _::binary>> -> {:error, :bidi, line, column}
<<226, 128, 174, _::binary>> -> {:error, :bidi, line, column}
<<239, 187, 191, _::binary>> -> {:error, :zero_width, line, column}
<<226, 128, 141, _::binary>> -> {:error, :zero_width, line, column}
<<226, 128, 140, _::binary>> -> {:error, :zero_width, line, column}
<<226, 128, 139, _::binary>> -> {:error, :zero_width, line, column}
<<226, 129, 160, _::binary>> -> {:error, :zero_width, line, column}
<<225, 158, 181, _::binary>> -> {:error, :zero_width, line, column}
<<225, 158, 180, _::binary>> -> {:error, :zero_width, line, column}
<<225, 160, 142, _::binary>> -> {:error, :zero_width, line, column}
<<205, 143, _::binary>> -> {:error, :cgj, line, column}
<<9, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<32, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<194, 160, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<225, 154, 128, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<226, 128, 130, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<226, 128, 131, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<226, 128, 137, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<226, 128, 175, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<226, 129, 159, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<227, 128, 128, rest::binary>> -> lex(rest, context, line, column+1, acc)
<<194, 133, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<226, 128, 168, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<226, 128, 169, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<10, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<11, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<12, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<13, rest::binary>> -> lex(rest, context, line+1, 0, acc)
<<?., rest::binary>> ->
column = column+1
case acc do
[{t, _, _}|_] when t in ~w[ident double_quote bracket]a ->
lex(rest, context, line, column, node(:dot, :operator, line, column, line, column, context, [], acc))
_ ->
num(rest, [?.], context, line, column, 0, acc)
end
<<?;, rest::binary>> ->
column = column+1
lex(rest, context, line, column, node(:colon, :delimiter, line, column, line, column, context, [], acc))
<<?,, rest::binary>> ->
column = column+1
lex(rest, context, line, column, node(:comma, :delimiter, line, column, line, column, context, [], acc))
<<?-, ?-, rest::binary>> -> comment(rest, [], line, column+1, context, line, column+1, acc)
<<?/, ?*, rest::binary>> -> comments(rest, [], line, column+1, context, line, column+1, acc)
<<?{, ?{, rest::binary>> -> double_brace(rest, [], line, column+1, 0, context, 0, 1, acc)
<<?`, rest::binary>> -> backtick(rest, [], line, column+1, context, line, column, acc)
<<?', rest::binary>> -> quote(rest, [], line, column+1, context, line, column, acc)
<<?", rest::binary>> -> double_quote(rest, [], line, column+1, context, line, column, acc)
<<?0, ?x, rest::binary>> -> hex(rest, [?x, ?0], context, line, column+1, 1, acc)
<<?0, ?X, rest::binary>> -> hex(rest, [?X, ?0], context, line, column+1, 1, acc)
<<?0, ?b, rest::binary>> -> bin(rest, [?b, ?0], context, line, column+1, 1, acc)
<<?0, ?B, rest::binary>> -> bin(rest, [?B, ?0], context, line, column+1, 1, acc)
<<?0, ?o, rest::binary>> -> oct(rest, [?o, ?0], context, line, column+1, 1, acc)
<<?0, ?O, rest::binary>> -> oct(rest, [?O, ?0], context, line, column+1, 1, acc)
<<?!, rest::binary>> -> special(rest, [?!], context, line, column+1, 0, acc)
<<?#, rest::binary>> -> special(rest, [?#], context, line, column+1, 0, acc)
<<?$, rest::binary>> -> special(rest, [?$], context, line, column+1, 0, acc)
<<?%, rest::binary>> -> special(rest, [?%], context, line, column+1, 0, acc)
<<?&, rest::binary>> -> special(rest, [?&], context, line, column+1, 0, acc)
<<?*, rest::binary>> -> special(rest, [?*], context, line, column+1, 0, acc)
<<?+, rest::binary>> -> special(rest, [?+], context, line, column+1, 0, acc)
<<?-, rest::binary>> -> special(rest, [?-], context, line, column+1, 0, acc)
<<?/, rest::binary>> -> special(rest, [?/], context, line, column+1, 0, acc)
<<?:, rest::binary>> -> special(rest, [?:], context, line, column+1, 0, acc)
<<?<, rest::binary>> -> special(rest, [?<], context, line, column+1, 0, acc)
<<?=, rest::binary>> -> special(rest, [?=], context, line, column+1, 0, acc)
<<?>, rest::binary>> -> special(rest, [?>], context, line, column+1, 0, acc)
<<??, rest::binary>> -> special(rest, [??], context, line, column+1, 0, acc)
<<?@, rest::binary>> -> special(rest, [?@], context, line, column+1, 0, acc)
<<?^, rest::binary>> -> special(rest, [?^], context, line, column+1, 0, acc)
<<?|, rest::binary>> -> special(rest, [?|], context, line, column+1, 0, acc)
<<?~, rest::binary>> -> special(rest, [?~], context, line, column+1, 0, acc)
<<?_, rest::binary>> -> ident(rest, [?_], context, line, column+1, 0, acc)
<<?0, rest::binary>> -> num(rest, [?0], context, line, column+1, 0, acc)
<<?1, rest::binary>> -> num(rest, [?1], context, line, column+1, 0, acc)
<<?2, rest::binary>> -> num(rest, [?2], context, line, column+1, 0, acc)
<<?3, rest::binary>> -> num(rest, [?3], context, line, column+1, 0, acc)
<<?4, rest::binary>> -> num(rest, [?4], context, line, column+1, 0, acc)
<<?5, rest::binary>> -> num(rest, [?5], context, line, column+1, 0, acc)
<<?6, rest::binary>> -> num(rest, [?6], context, line, column+1, 0, acc)
<<?7, rest::binary>> -> num(rest, [?7], context, line, column+1, 0, acc)
<<?8, rest::binary>> -> num(rest, [?8], context, line, column+1, 0, acc)
<<?9, rest::binary>> -> num(rest, [?9], context, line, column+1, 0, acc)
<<?A, rest::binary>> -> ident(rest, [?A], context, line, column+1, 0, acc)
<<?B, rest::binary>> -> ident(rest, [?B], context, line, column+1, 0, acc)
<<?C, rest::binary>> -> ident(rest, [?C], context, line, column+1, 0, acc)
<<?D, rest::binary>> -> ident(rest, [?D], context, line, column+1, 0, acc)
<<?E, rest::binary>> -> ident(rest, [?E], context, line, column+1, 0, acc)
<<?F, rest::binary>> -> ident(rest, [?F], context, line, column+1, 0, acc)
<<?G, rest::binary>> -> ident(rest, [?G], context, line, column+1, 0, acc)
<<?H, rest::binary>> -> ident(rest, [?H], context, line, column+1, 0, acc)
<<?I, rest::binary>> -> ident(rest, [?I], context, line, column+1, 0, acc)
<<?J, rest::binary>> -> ident(rest, [?J], context, line, column+1, 0, acc)
<<?K, rest::binary>> -> ident(rest, [?K], context, line, column+1, 0, acc)
<<?L, rest::binary>> -> ident(rest, [?L], context, line, column+1, 0, acc)
<<?M, rest::binary>> -> ident(rest, [?M], context, line, column+1, 0, acc)
<<?N, rest::binary>> -> ident(rest, [?N], context, line, column+1, 0, acc)
<<?O, rest::binary>> -> ident(rest, [?O], context, line, column+1, 0, acc)
<<?P, rest::binary>> -> ident(rest, [?P], context, line, column+1, 0, acc)
<<?Q, rest::binary>> -> ident(rest, [?Q], context, line, column+1, 0, acc)
<<?R, rest::binary>> -> ident(rest, [?R], context, line, column+1, 0, acc)
<<?S, rest::binary>> -> ident(rest, [?S], context, line, column+1, 0, acc)
<<?T, rest::binary>> -> ident(rest, [?T], context, line, column+1, 0, acc)
<<?U, rest::binary>> -> ident(rest, [?U], context, line, column+1, 0, acc)
<<?V, rest::binary>> -> ident(rest, [?V], context, line, column+1, 0, acc)
<<?W, rest::binary>> -> ident(rest, [?W], context, line, column+1, 0, acc)
<<?X, rest::binary>> -> ident(rest, [?X], context, line, column+1, 0, acc)
<<?Y, rest::binary>> -> ident(rest, [?Y], context, line, column+1, 0, acc)
<<?Z, rest::binary>> -> ident(rest, [?Z], context, line, column+1, 0, acc)
<<?a, rest::binary>> -> ident(rest, [?a], context, line, column+1, 0, acc)
<<?b, rest::binary>> -> ident(rest, [?b], context, line, column+1, 0, acc)
<<?c, rest::binary>> -> ident(rest, [?c], context, line, column+1, 0, acc)
<<?d, rest::binary>> -> ident(rest, [?d], context, line, column+1, 0, acc)
<<?e, rest::binary>> -> ident(rest, [?e], context, line, column+1, 0, acc)
<<?f, rest::binary>> -> ident(rest, [?f], context, line, column+1, 0, acc)
<<?g, rest::binary>> -> ident(rest, [?g], context, line, column+1, 0, acc)
<<?h, rest::binary>> -> ident(rest, [?h], context, line, column+1, 0, acc)
<<?i, rest::binary>> -> ident(rest, [?i], context, line, column+1, 0, acc)
<<?j, rest::binary>> -> ident(rest, [?j], context, line, column+1, 0, acc)
<<?k, rest::binary>> -> ident(rest, [?k], context, line, column+1, 0, acc)
<<?l, rest::binary>> -> ident(rest, [?l], context, line, column+1, 0, acc)
<<?m, rest::binary>> -> ident(rest, [?m], context, line, column+1, 0, acc)
<<?n, rest::binary>> -> ident(rest, [?n], context, line, column+1, 0, acc)
<<?o, rest::binary>> -> ident(rest, [?o], context, line, column+1, 0, acc)
<<?p, rest::binary>> -> ident(rest, [?p], context, line, column+1, 0, acc)
<<?q, rest::binary>> -> ident(rest, [?q], context, line, column+1, 0, acc)
<<?r, rest::binary>> -> ident(rest, [?r], context, line, column+1, 0, acc)
<<?s, rest::binary>> -> ident(rest, [?s], context, line, column+1, 0, acc)
<<?t, rest::binary>> -> ident(rest, [?t], context, line, column+1, 0, acc)
<<?u, rest::binary>> -> ident(rest, [?u], context, line, column+1, 0, acc)
<<?v, rest::binary>> -> ident(rest, [?v], context, line, column+1, 0, acc)
<<?w, rest::binary>> -> ident(rest, [?w], context, line, column+1, 0, acc)
<<?x, rest::binary>> -> ident(rest, [?x], context, line, column+1, 0, acc)
<<?y, rest::binary>> -> ident(rest, [?y], context, line, column+1, 0, acc)
<<?(, rest::binary>> ->
column = column+1
case lex(rest, context, line, column, []) do
{rest, context, l, c, []=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, 0, 0}
[] -> {0, 0, 0, 0}
end
lex(rest, context, l, c, [{:paren, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{rest, context, l, c, [{_, [{:span, {_, _, eel, eec}}|_], _}|_]=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, l-eel, (c-eec)-1}
[] -> {0, 0, l-eel, (c-eec)-1}
end
lex(rest, context, l, c, [{:paren, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{end_line, end_column, _context, _acc} ->
{:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"(", expected_delimiter: :")"}
end
<<?[, rest::binary>> ->
column = column+1
case lex(rest, context, line, column, []) do
{rest, context, l, c, []=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, 0, 0}
[] -> {0, 0, 0, 0}
end
lex(rest, context, l, c, [{:bracket, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{rest, context, l, c, [{_, [{:span, {_, _, eel, eec}}|_], _}|_]=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, l-eel, (c-eec)-1}
[] -> {0, 0, l-eel, (c-eec)-1}
end
lex(rest, context, l, c, [{:bracket, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{end_line, end_column, _context, _acc} ->
{:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"[", expected_delimiter: :"]"}
end
<<?{, rest::binary>> ->
column = column+1
case lex(rest, context, line, column, []) do
{rest, context, l, c, []=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, 0, 0}
[] -> {0, 0, 0, 0}
end
lex(rest, context, l, c, [{:brace, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{rest, context, l, c, [{_, [{:span, {_, _, eel, eec}}|_], _}|_]=data} ->
offset = case acc do
[{_, [{:span, {_, _, el, ec}}|_], _}|_] -> {line-el, (column-ec)-1, l-eel, (c-eec)-1}
[] -> {0, 0, l-eel, (c-eec)-1}
end
lex(rest, context, l, c, [{:brace, [span: {line, column, l, c}, offset: offset, type: :expression, file: context.file], data}|acc])
{end_line, end_column, _context, _acc} ->
{:error, file: context.file, end_line: end_line, end_column: end_column, line: line, column: column, opening_delimiter: :"{", expected_delimiter: :"}"}
end
<<?}, rest::binary>> -> {rest, context, line, column+1, acc}
<<?), rest::binary>> -> {rest, context, line, column+1, acc}
<<?], rest::binary>> -> {rest, context, line, column+1, acc}
# <<b::utf8, rest::binary>> when Unicode.Set.match?(b, "[[:Lu:], [:Ll:], [:Lt:], [:Lm:], [:Lo:], [:Nl:]]") ->
# ident(rest, [b], context, line, column+1, 0, acc)
"" -> {line, column, context, acc}
rest -> ident_start(rest, context, line, column, acc)
end
end
case_ast =
for b <- tl(Unicode.Set.to_pattern!("[[:Lu:], [:Ll:], [:Lt:], [:Lm:], [:Lo:], [:Nl:]]")) do
hd(
quote do
<<unquote(b), rest::binary>> -> ident(rest, [unquote(b)], var!(context), var!(line), var!(column)+1, 0, var!(acc))
end
)
end
defp ident_start(rest, context, line, column, acc) do
case rest do
unquote(case_ast)
end
end