Skip to content

Commit dfa7d58

Browse files
committed
Use new OTP28.1 :re.import for regexes
erlang/otp#9976
1 parent d21a13b commit dfa7d58

File tree

2 files changed

+43
-12
lines changed

2 files changed

+43
-12
lines changed

lib/elixir/lib/kernel.ex

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6647,13 +6647,20 @@ defmodule Kernel do
66476647
end
66486648

66496649
defp compile_regex(binary_or_tuple, options) do
6650-
# TODO: Remove this when we require Erlang/OTP 28+
6651-
case is_binary(binary_or_tuple) and :erlang.system_info(:otp_release) < [?2, ?8] do
6652-
true ->
6653-
Macro.escape(Regex.compile!(binary_or_tuple, :binary.list_to_bin(options)))
6650+
bin_opts = :binary.list_to_bin(options)
66546651

6655-
false ->
6656-
quote(do: Regex.compile!(unquote(binary_or_tuple), unquote(:binary.list_to_bin(options))))
6652+
cond do
6653+
# TODO: Remove this when we require Erlang/OTP 28+
6654+
is_binary(binary_or_tuple) and :erlang.system_info(:otp_release) < [?2, ?8] ->
6655+
Macro.escape(Regex.compile!(binary_or_tuple, bin_opts))
6656+
6657+
# TODO: Remove this when we require Erlang/OTP 28.1+
6658+
is_binary(binary_or_tuple) and Code.ensure_loaded?(:re) and
6659+
function_exported?(:re, :import, 1) ->
6660+
Macro.escape(Regex.compile_export!(binary_or_tuple, bin_opts))
6661+
6662+
true ->
6663+
quote(do: Regex.compile!(unquote(binary_or_tuple), unquote(bin_opts)))
66576664
end
66586665
end
66596666

lib/elixir/lib/regex.ex

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,21 +202,23 @@ defmodule Regex do
202202
"""
203203
@spec compile(binary, binary | [term]) :: {:ok, t} | {:error, term}
204204
def compile(source, opts \\ "") when is_binary(source) do
205-
do_compile(source, opts)
205+
do_compile(source, opts, false)
206206
end
207207

208-
defp do_compile(source, opts) when is_binary(opts) do
208+
defp do_compile(source, opts, export?) when is_binary(opts) do
209209
case translate_options(opts, []) do
210210
{:error, rest} ->
211211
{:error, {:invalid_option, rest}}
212212

213213
translated_opts ->
214-
do_compile(source, translated_opts)
214+
do_compile(source, translated_opts, export?)
215215
end
216216
end
217217

218-
defp do_compile(source, opts) when is_list(opts) do
219-
case :re.compile(source, opts) do
218+
defp do_compile(source, opts, export?) when is_list(opts) do
219+
compile_opts = if export?, do: [:export | opts], else: opts
220+
221+
case :re.compile(source, compile_opts) do
220222
{:ok, re_pattern} ->
221223
{:ok, %Regex{re_pattern: re_pattern, source: source, opts: opts}}
222224

@@ -225,6 +227,11 @@ defmodule Regex do
225227
end
226228
end
227229

230+
@spec compile_export(binary, binary | [term]) :: {:ok, t} | {:error, term}
231+
def compile_export(source, opts \\ "") when is_binary(source) do
232+
do_compile(source, opts, true)
233+
end
234+
228235
@doc """
229236
Compiles the regular expression and raises `Regex.CompileError` in case of errors.
230237
"""
@@ -236,6 +243,17 @@ defmodule Regex do
236243
end
237244
end
238245

246+
@doc """
247+
Compiles the regular expression and raises `Regex.CompileError` in case of errors.
248+
"""
249+
@spec compile_export!(binary, binary | [term]) :: t
250+
def compile_export!(source, options \\ "") when is_binary(source) do
251+
case compile_export(source, options) do
252+
{:ok, regex} -> regex
253+
{:error, {reason, at}} -> raise Regex.CompileError, "#{reason} at position #{at}"
254+
end
255+
end
256+
239257
@doc """
240258
Recompiles the existing regular expression if necessary.
241259
@@ -506,6 +524,7 @@ defmodule Regex do
506524
"""
507525
@spec names(t) :: [String.t()]
508526
def names(%Regex{re_pattern: re_pattern}) do
527+
re_pattern = maybe_import_pattern(re_pattern)
509528
{:namelist, names} = :re.inspect(re_pattern, :namelist)
510529
names
511530
end
@@ -576,10 +595,15 @@ defmodule Regex do
576595
%Regex{source: source, opts: compile_opts} = regex
577596
:re.run(string, source, compile_opts ++ options)
578597
else
579-
_ -> :re.run(string, re_pattern, options)
598+
_ -> :re.run(string, maybe_import_pattern(re_pattern), options)
580599
end
581600
end
582601

602+
defp maybe_import_pattern({:re_exported_pattern, _, _, _, _} = exported),
603+
do: :re.import(exported)
604+
605+
defp maybe_import_pattern(re_pattern), do: re_pattern
606+
583607
@typedoc """
584608
Options for regex functions that capture matches.
585609
"""

0 commit comments

Comments
 (0)