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>'&lt;'</c>, <c>'=&lt;'</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

openSUSE Build Service is sponsored by