Skip to content

Commit

Permalink
prematch handling
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszsamson committed Dec 22, 2024
1 parent 8397525 commit 4dc611b
Show file tree
Hide file tree
Showing 4 changed files with 1,027 additions and 1,013 deletions.
37 changes: 24 additions & 13 deletions lib/elixir_sense/core/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -607,8 +607,6 @@ defmodule ElixirSense.Core.Compiler do
end

_ ->
# prematch

case e do
%{context: :guard} ->
:raise
Expand Down Expand Up @@ -845,6 +843,7 @@ defmodule ElixirSense.Core.Compiler do
env = %{module: module}
)
when module != nil do
state_orig_prematch = state.prematch
{opts, state, env} = expand(opts, state, env)
# elixir does validation here
target = Keyword.get(opts, :to, :__unknown__)
Expand Down Expand Up @@ -921,7 +920,7 @@ defmodule ElixirSense.Core.Compiler do
)
end)

{[], state, env}
{[], %{state | prematch: state_orig_prematch}, env}
end

defp expand_macro(
Expand Down Expand Up @@ -1780,21 +1779,22 @@ defmodule ElixirSense.Core.Compiler do
expanded_arg
end)

prematch =
if Version.match?(System.version(), ">= 1.15.0-dev") do
if Version.match?(System.version(), ">= 1.18.0-dev") do
:none
guard_prematch =
if Version.match?(System.version(), ">= 1.18.0-dev") do
:none
else
if Version.match?(System.version(), ">= 1.15.0-dev") do
# Code.get_compiler_option(:on_undefined_variable)
:raise
else
Code.get_compiler_option(:on_undefined_variable)
:warn
end
else
:warn
end

{e_guard, state, env_for_expand} =
__MODULE__.Clauses.guard(
guards,
%{state | prematch: prematch},
%{state | prematch: guard_prematch},
%{env_for_expand | context: :guard}
)

Expand All @@ -1804,8 +1804,19 @@ defmodule ElixirSense.Core.Compiler do

env_for_expand = %{env_for_expand | context: nil}

prematch =
if Version.match?(System.version(), ">= 1.18.0-dev") do
state.prematch
else
if Version.match?(System.version(), ">= 1.15.0-dev") do
Code.get_compiler_option(:on_undefined_variable)
else
:warn
end
end

state =
state
%{state | prematch: prematch}
|> State.add_current_env_to_line(meta, env_for_expand)
|> State.add_func_to_index(
env,
Expand Down Expand Up @@ -1855,7 +1866,7 @@ defmodule ElixirSense.Core.Compiler do
end

# result of def expansion is fa tuple
{{name, arity}, state, env}
{{name, arity}, %{state | prematch: state_orig.prematch}, env}
end

defp expand_macro(
Expand Down
23 changes: 8 additions & 15 deletions lib/elixir_sense/core/compiler/clauses.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,10 @@ defmodule ElixirSense.Core.Compiler.Clauses do
alias ElixirSense.Core.TypeInference

def parallel_match(meta, expr, s, e = %{context: :match}) do
# #elixir_ex{vars={_Read, Write}} = S,
# becomes pattern-matching on our struct:
%{vars: {_read, write}} = s

matches = unpack_match(expr, meta, [])

# {[{_, EHead} | ETail], EWrites, SM, EM} =
# lists:foldl(fun(...) -> ... end, {[], [], S, E}, Matches),
#
# in Elixir we use Enum.reduce/3:
# {[{_, e_head} | e_tail], e_writes, sm, em} =
# Enum.reduce(matches, {[], [], s, e}, fn {e_meta, match}, {acc_matches, acc_writes, si, ei} ->
# # #elixir_ex{vars={Read, _Write}} = SI
Expand Down Expand Up @@ -66,19 +60,13 @@ defmodule ElixirSense.Core.Compiler.Clauses do
e_tail
)

# #elixir_ex{vars={VRead, _}, prematch={PRead, Cycles, PInfo}} = SM,
%{vars: {v_read, _}, prematch: {p_read, cycles, p_info}} = sm

# {PCycles, PWrites} = store_cycles(EWrites, Cycles, #{}),
{p_cycles, p_writes} = store_cycles(e_writes, cycles, %{})

# VWrite = (Write /= false) andalso elixir_env:merge_vars(Write, PWrites),
# In Erlang, "/=" is "not equal to" and "andalso" is a short-circuit AND.
# In Elixir, we do "!=" and "and".
v_write =
write != false && State.merge_vars(write, p_writes)

# {EMatch, SM#elixir_ex{vars={VRead, VWrite}, prematch={PRead, PCycles, PInfo}}, EM}.
updated_sm = %{
sm
| vars: {v_read, v_write},
Expand Down Expand Up @@ -216,10 +204,15 @@ defmodule ElixirSense.Core.Compiler.Clauses do
end

defp guarded_head(when_meta, args, guard, s, e) do
prematch = s.prematch

{e_args, sa, ea} = match(&Compiler.expand_args/3, args, s, s, e)
# TODO should we restore prematch? 1.18 does not do that

prematch =
if Version.match?(System.version(), ">= 1.18.0-dev") do
sa.prematch
else
s.prematch
end

{e_guard, sg, eg} = guard(guard, %{sa | prematch: prematch}, %{ea | context: :guard})

type_info = TypeInference.Guard.type_information_from_guards(e_guard)
Expand Down
5 changes: 4 additions & 1 deletion lib/elixir_sense/core/metadata_builder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ defmodule ElixirSense.Core.MetadataBuilder do
cursor_position: cursor_position,
prematch:
if Version.match?(System.version(), ">= 1.15.0-dev") do
Code.get_compiler_option(:on_undefined_variable)
if(Version.match?(System.version(), ">= 1.18.0-dev"),
do: :none,
else: Code.get_compiler_option(:on_undefined_variable)
)
else
:warn
end
Expand Down
Loading

0 comments on commit 4dc611b

Please sign in to comment.