defmodule Guesswork.Ast.Assign do @moduledoc """ A simple assignment of a value to a variable. """ defstruct [:binding, :value] alias Guesswork.Ast.Variable alias Guesswork.Ast.Term alias Guesswork.Ast.Statement.Opts alias Guesswork.Answer alias Guesswork.Answer.Binding alias Guesswork.Telemetry.EventHandler @type t() :: %__MODULE__{binding: Variable.t() | Term.entity(), value: Term.entity()} @spec new(Variable.t(), Term.entity()) :: t() def new(variable, value), do: %__MODULE__{binding: variable, value: value} defimpl Guesswork.Ast.Term do alias Guesswork.Ast.Assign def concrete?(%Assign{binding: %Variable{}}), do: false def concrete?(_), do: true def get_variables(%Assign{binding: %Variable{} = variable}), do: [variable] def get_variables(_), do: [] end defimpl Guesswork.Ast.Statement do alias Guesswork.Ast.Assign def simplify(statement) do statement end def substitute(%Assign{binding: binding} = statement, env) do case Map.fetch(env, binding) do :error -> statement {:ok, value} -> %Assign{statement | binding: value} end end def resolve( %Assign{binding: %Variable{display: display}, value: value}, negated, %Opts{query_id: query_id} ) do :telemetry.execute(EventHandler.assignment_event_name(), %{count: 1}, %{query_id: query_id}) [ %Answer{ tests: [], bindings: %{display => Binding.new(value, negated)}, query_id: query_id } ] end def resolve( %Assign{binding: bound, value: value}, negated, %Opts{query_id: query_id} ) when bound == value != negated, do: [Answer.new(query_id)] def resolve(_statement, _negated, _opts), do: [] end end