Commit 1533add81b006e808d1a3933f962e2f7b7bd879f

Thomas de Grivel 2022-02-18T10:08:21

VARIABLES

diff --git a/lib/pure.ex b/lib/pure.ex
index 204457b..1ee9d18 100644
--- a/lib/pure.ex
+++ b/lib/pure.ex
@@ -28,12 +28,9 @@ defmodule Pure do
   """
     def is_guard?(quoted, env) do
     {erl, _, _, _env} = :elixir.quoted_to_erl(quoted, env)
-    IO.inspect(erl, limit: :infinity)
-    if :erl_lint.is_guard_test(erl) do
-      true
-    else
-      false
-    end
+    result = :erl_lint.is_guard_test(erl)
+    IO.inspect([:is_guard?, quoted, result])
+    result
   end
 
   @doc """
@@ -54,7 +51,7 @@ defmodule Pure do
 
   ## Examples
 
-      iex> Pure.string_is_match?("{a, b} = File.read(:stdin)", __ENV__)
+      iex> Pure.string_is_match?("{a, b} = {1, 2}", __ENV__)
       true
   """
   def string_is_match?(str, env) when is_binary(str) do
@@ -71,22 +68,51 @@ defmodule Pure do
       true
   """
   def is_match?(quoted, env) do
-    IO.inspect(quoted)
     {erl, _, _, _env} = :elixir.quoted_to_erl(quoted, env)
-    IO.inspect(erl, limit: :infinity)
+    #IO.inspect(erl)
     case erl do
       {:match, _, a, b} ->
         a_is_pattern? = :pure.is_pattern_expr(a)
         b_is_guard? = :erl_lint.is_guard_test(b)
-        IO.inspect([a: a, is_pattern?: a_is_pattern?])
-        IO.inspect([b: b, is_guard?: b_is_guard?])
-        a_is_pattern? && b_is_guard?
-      _ -> false
+        result = a_is_pattern? && b_is_guard?
+        IO.inspect([:is_match?, quoted,
+                    a: a, is_pattern?: a_is_pattern?,
+                    b: b, is_guard?: b_is_guard?,
+                    result: result])
+        result
+      _ ->
+        IO.inspect([:is_match?, quoted, false])
+        false
     end
   end    
 
-  def is_pure?(q) do
-    is_guard?(q, __ENV__) || is_match?(q, __ENV__)
+  def is_pure?(quoted = {:__block__, _, block}, env) do
+    is_pure_block?(quoted, env, block, [])
+  end
+  def is_pure?(quoted, env) do
+    result = is_guard?(quoted, env) || is_match?(quoted, env)
+    IO.inspect([:is_pure?, quoted, result])
+    result
+  end
+
+  def is_pure_block?(quoted, _env, [], _acc) do
+    IO.inspect([:is_pure?, quoted, true])
+    true
+  end
+  def is_pure_block?(quoted, env, [first | rest], acc) do
+    env = env_eval(env, {:__block__, 1, Enum.reverse(acc)})
+    if is_pure?(first, env) do
+      is_pure_block?(quoted, env, rest, [first | acc])
+    else
+      IO.inspect([:is_pure?, quoted, false])
+      false
+    end
+  end
+
+  def env_eval(env, quoted) do
+    IO.inspect([:env_eval, quoted])
+    {env1, _} = Code.eval_quoted(quote do unquote(quoted); __ENV__ end, [], env)
+    env1
   end
 
   defmacro eval(str) when is_binary(str) do
@@ -96,15 +122,8 @@ defmodule Pure do
       Pure.eval(unquote(q))
     end
   end
-  defmacro eval(q = {:__block__, _, l}) when is_list(l) do
-    if Enum.all?(l, fn i ->
-          is_pure?(i)
-        end) do
-      q
-    end
-  end
   defmacro eval(q) do
-    if is_pure?(q) do
+    if is_pure?(q, __ENV__) do
       q
     else
       raise ArgumentError, "not a pure expression: #{Macro.to_string(q)}"