File 3261-erts-stdlib-Allow-binary-bifs-in-match_spec-and-trac.patch of Package erlang
From 954fd530e44cf75de718c07be1ab332b1ea27e80 Mon Sep 17 00:00:00 2001
From: Danil Zagoskin <z@gosk.in>
Date: Mon, 5 Jul 2021 19:35:16 +0300
Subject: [PATCH] erts,stdlib: Allow binary bifs in match_spec and trace
pattern guards
This commit adds byte_size/2, binary_part/2 and binary_part/3 to
a valid guard lists, extending functionality of ets select and tracing.
---
erts/doc/src/match_spec.xml | 9 +++++---
erts/emulator/beam/erl_db_util.c | 18 ++++++++++++++++
lib/stdlib/doc/src/ms_transform.xml | 4 ++--
lib/stdlib/src/ms_transform.erl | 3 +++
lib/stdlib/test/ms_transform_SUITE.erl | 29 +++++++++++++++++++++++++-
5 files changed, 57 insertions(+), 6 deletions(-)
diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml
index 16fe2c8a40..ca8a1146b3 100644
--- a/erts/doc/src/match_spec.xml
+++ b/erts/doc/src/match_spec.xml
@@ -113,8 +113,9 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> |
<c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
- <c><![CDATA[bit_size]]></c> |
+ <c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c>
<c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
+ <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -195,8 +196,9 @@
<c><![CDATA[length]]></c> | <c><![CDATA[map_get]]></c> |
<c><![CDATA[map_size]]></c> | <c><![CDATA[node]]></c> |
<c><![CDATA[round]]></c> | <c><![CDATA[size]]></c> |
- <c><![CDATA[bit_size]]></c> |
+ <c><![CDATA[bit_size]]></c> | <c><![CDATA[byte_size]]></c>
<c><![CDATA[tl]]></c> | <c><![CDATA[trunc]]></c> |
+ <c><![CDATA[binary_part]]></c> |
<c><![CDATA['+']]></c> | <c><![CDATA['-']]></c> |
<c><![CDATA['*']]></c> | <c><![CDATA['div']]></c> |
<c><![CDATA['rem']]></c> | <c><![CDATA['band']]></c> |
@@ -273,7 +275,8 @@
</item>
<tag><c>abs</c>, <c>element</c>, <c>hd</c>, <c>length</c>,
<c>map_get</c>, <c>map_size</c>, <c>node</c>, <c>round</c>,
- <c>size</c>, <c>bit_size</c>, <c>tl</c>, <c>trunc</c>, <c>'+'</c>,
+ <c>size</c>, <c>bit_size</c>, <c>byte_size</c>, <c>tl</c>,
+ <c>trunc</c>, <c>binary_part</c>, <c>'+'</c>,
<c>'-'</c>, <c>'*'</c>, <c>'div'</c>, <c>'rem'</c>, <c>'band'</c>,
<c>'bor'</c>, <c>'bxor'</c>, <c>'bnot'</c>, <c>'bsl'</c>,
<c>'bsr'</c>, <c>'>'</c>, <c>'>='</c>, <c>'<'</c>, <c>'=<'</c>,
diff --git a/erts/emulator/beam/erl_db_util.c b/erts/emulator/beam/erl_db_util.c
index c799745a6e..952a702a21 100644
--- a/erts/emulator/beam/erl_db_util.c
+++ b/erts/emulator/beam/erl_db_util.c
@@ -675,6 +675,24 @@ static DMCGuardBif guard_tab[] =
1,
DBIF_ALL
},
+ {
+ am_byte_size,
+ &byte_size_1,
+ 1,
+ DBIF_ALL
+ },
+ {
+ am_binary_part,
+ &binary_part_2,
+ 2,
+ DBIF_ALL
+ },
+ {
+ am_binary_part,
+ &binary_part_3,
+ 3,
+ DBIF_ALL
+ },
{
am_tl,
&tl_1,
diff --git a/lib/stdlib/doc/src/ms_transform.xml b/lib/stdlib/doc/src/ms_transform.xml
index bde9223eb0..0339af04c4 100644
--- a/lib/stdlib/doc/src/ms_transform.xml
+++ b/lib/stdlib/doc/src/ms_transform.xml
@@ -389,8 +389,8 @@ ets:select(emp_tab, ets:fun2ms(
<item>
<p>The guard BIFs: <c>abs</c>, <c>element</c>,
<c>hd</c>, <c>length</c>,
- <c>node</c>, <c>round</c>, <c>size</c>, <c>tl</c>, <c>trunc</c>,
- <c>self</c></p>
+ <c>node</c>, <c>round</c>, <c>size</c>, <c>byte_size</c>, <c>tl</c>,
+ <c>trunc</c>, <c>binary_part</c>, <c>self</c></p>
</item>
</list>
diff --git a/lib/stdlib/src/ms_transform.erl b/lib/stdlib/src/ms_transform.erl
index afa886be14..5bffb3c024 100644
--- a/lib/stdlib/src/ms_transform.erl
+++ b/lib/stdlib/src/ms_transform.erl
@@ -974,8 +974,11 @@ real_guard_function(node,1) -> true;
real_guard_function(round,1) -> true;
real_guard_function(size,1) -> true;
real_guard_function(bit_size,1) -> true;
+real_guard_function(byte_size,1) -> true;
real_guard_function(map_size,1) -> true;
real_guard_function(map_get,2) -> true;
+real_guard_function(binary_part,2) -> true;
+real_guard_function(binary_part,3) -> true;
real_guard_function(tl,1) -> true;
real_guard_function(trunc,1) -> true;
real_guard_function(self,0) -> true;
diff --git a/lib/stdlib/test/ms_transform_SUITE.erl b/lib/stdlib/test/ms_transform_SUITE.erl
index 0aefda4724..c997691c43 100644
--- a/lib/stdlib/test/ms_transform_SUITE.erl
+++ b/lib/stdlib/test/ms_transform_SUITE.erl
@@ -36,6 +36,7 @@
-export([autoimported/1]).
-export([semicolon/1]).
-export([bitsyntax/1]).
+-export([binary_bifs/1]).
-export([record_defaults/1]).
-export([andalso_orelse/1]).
-export([float_1_function/1]).
@@ -57,7 +58,7 @@ suite() ->
all() ->
[from_shell, basic_ets, basic_dbg, records,
- record_index, multipass, bitsyntax, record_defaults,
+ record_index, multipass, bitsyntax, binary_bifs, record_defaults,
andalso_orelse, float_1_function, action_function,
warnings, no_warnings, top_match, old_guards, autoimported,
semicolon, eep37, otp_14454].
@@ -253,6 +254,32 @@ bitsyntax(Config) when is_list(Config) ->
" end)">>),
ok.
+
+%% Test that binary BIFs byte_size/1, binary_part/2, binary_part/3 are accepted
+binary_bifs(Config) when is_list(Config) ->
+ setup(Config),
+ TestSet = [{<<"hello">>, <<"world">>}, {<<"souldn't">>, <<"match">>}],
+ RunMS = fun(MS) -> ets:match_spec_run(TestSet, ets:match_spec_compile(MS)) end,
+ % check byte_size/1
+ MS1 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when byte_size(A) == 5 -> {A, byte_size(B)} end)">>),
+ [{{'$1','$2'},
+ [{'==',{byte_size,'$1'},5}],
+ [{{'$1',{byte_size,'$2'}}}]}] = MS1,
+ [{<<"hello">>, 5}] = RunMS(MS1),
+ % check binary_part/2
+ MS2 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when binary_part(A, {1, 2}) == <<\"el\">> -> binary_part(B, {2, 3}) end)">>),
+ [{{'$1','$2'},
+ [{'==',{binary_part,'$1',{{1,2}}},<<"el">>}],
+ [{binary_part,'$2',{{2,3}}}]}] = MS2,
+ [<<"rld">>] = RunMS(MS2),
+ % check binary_part/3
+ MS3 = compile_and_run(<<"ets:fun2ms(fun({A, B}) when binary_part(A, 1, 2) == <<\"el\">> -> binary_part(B, 2, 3) end)">>),
+ [{{'$1','$2'},
+ [{'==',{binary_part,'$1',1,2},<<"el">>}],
+ [{binary_part,'$2',2,3}]}] = MS3,
+ [<<"rld">>] = RunMS(MS3),
+ ok.
+
%% Test that record defaults works.
record_defaults(Config) when is_list(Config) ->
setup(Config),
--
2.31.1