aboutsummaryrefslogtreecommitdiff
path: root/lib/elixir_math_parser.ex
diff options
context:
space:
mode:
authorAnhgelus Morhtuuzh <william@herges.fr>2025-11-10 17:31:41 +0100
committerAnhgelus Morhtuuzh <william@herges.fr>2025-11-10 17:31:41 +0100
commit4840f480c8f255a6cf3b4eed291a00cea76b0cac (patch)
treed9baf898c1e961bb8ee5d181c38cce93b062129b /lib/elixir_math_parser.ex
parent037094a928653ed27f1f9d5497f637af1c5380e0 (diff)
feat(calc): supports function definition and evaluation
Diffstat (limited to 'lib/elixir_math_parser.ex')
-rw-r--r--lib/elixir_math_parser.ex40
1 files changed, 40 insertions, 0 deletions
diff --git a/lib/elixir_math_parser.ex b/lib/elixir_math_parser.ex
index 286829e..b7f080c 100644
--- a/lib/elixir_math_parser.ex
+++ b/lib/elixir_math_parser.ex
@@ -5,6 +5,7 @@ defmodule ElixirMathParser do
alias ElixirMathParser.Math.Rational
alias ElixirMathParser.Math.Calc
alias ElixirMathParser.Math.Conversion
+ alias ElixirMathParser.Math.Function
defp reduce_to_value({:int, _line, value}, _state) do
{:ok, Rational.new(value)}
@@ -76,11 +77,35 @@ defmodule ElixirMathParser do
end
end
+ defp reduce_to_value({:eval_func, {:var, line, var}, params}, state) do
+ if !Map.has_key?(state, var) do
+ {:error, line, "function " <> to_string(var) <> " not found"}
+ else
+ v = state[var]
+
+ # check if the mult is implicit
+ if Rational.is_rational(v) do
+ [head | _] = params
+ reduce_to_value({:mul_op, {:var, line, var}, head}, state)
+ else
+ params = Enum.map(params, fn v -> with {:ok, v} <- reduce_to_value(v, state), do: v end)
+
+ with {:ok, v} <- state[var] |> Function.eval(params) do
+ {:ok, v}
+ else
+ {:error, reason} -> {:error, line, reason}
+ {:error, line, reason} -> {:error, line, reason}
+ end
+ end
+ end
+ end
+
defp evaluate_tree([{:assign, {:var, line, lhs}, rhs} | tail], state) do
with {:ok, val} <- reduce_to_value(rhs, state) do
evaluate_tree(tail, Map.merge(state, %{lhs => val}))
else
{:error, reason} -> {:error, line, reason}
+ {:error, line, reason} -> {:error, line, reason}
end
end
@@ -92,6 +117,21 @@ defmodule ElixirMathParser do
end
end
+ defp evaluate_tree([{:assign_func, {:var, _line, name}, vars, expr} | tail], state) do
+ fun =
+ Function.new(
+ fn params, given ->
+ state =
+ Enum.reduce(given, state, fn {v, id}, acc -> Map.merge(acc, %{params[id] => v}) end)
+
+ reduce_to_value(expr, state)
+ end,
+ Enum.map(vars, fn {:var, _line, name} -> name end)
+ )
+
+ evaluate_tree(tail, Map.merge(state, %{name => fun}))
+ end
+
defp evaluate_tree([], state) do
{:ok, state}
end