# `Predicator.Visitors.StringVisitor`
[🔗](https://github.com/riddler/predicator-ex/blob/v9.4.1/lib/predicator/visitors/string_visitor.ex#L1)

Visitor that converts AST nodes back to string expressions.

This visitor implements the inverse of parsing - it takes an Abstract Syntax Tree
and generates a readable string representation. This is useful for debugging,
documentation, and round-trip testing.

A node's trailing slot is ignored: rendering a parsed AST and rendering the
same tree with `nil` in every slot produce identical strings. A caller
hand-building an AST supplies `nil` there - the slot is part of the node
shape, not an add-on.

## Examples

    iex> ast = {:literal, 42, nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "42"

    iex> ast = {:identifier, "limit", nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "limit"

    iex> ast = {:comparison, :gt, {:identifier, "limit", nil}, {:literal, 85, nil}, nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "limit > 85"

    iex> {:ok, ast} = Predicator.parse(~s(name == "John"))
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    ~s(name == "John")

    iex> ast = {:logical_and, {:literal, true, nil}, {:literal, false, nil}, nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "true AND false"

    iex> ast = {:logical_not, {:literal, true, nil}, nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "NOT true"

    iex> ast = {:function_call, "len", [{:identifier, "name", nil}], nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "len(name)"

    iex> ast = {:cast, {:identifier, "limit", nil}, "integer", nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "limit::integer"

    iex> ast = {:object, [], nil}
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "{}"

    iex> {:ok, ast} = Predicator.parse(~s({name: "John"}))
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    ~s({name: "John"})

    iex> {:ok, ast} = Predicator.parse(~s({"first name": "John"}))
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    ~s({"first name": "John"})

    iex> {:ok, ast} = Predicator.parse_program("if a { x = 1 } else if b { x = 2 }")
    iex> Predicator.Visitors.StringVisitor.visit(ast, [])
    "if a { x = 1 } else if b { x = 2 }"

# `visit`

```elixir
@spec visit(
  Predicator.Parser.visitable(),
  keyword()
) :: binary()
```

Visits an AST node and returns its string representation.

## Parameters

- `ast_node` - The AST node to convert to a string
- `opts` - Optional visitor options:
  - `:parentheses` - `:minimal` (default) | `:explicit` | `:none`
  - `:spacing` - `:normal` (default) | `:compact` | `:verbose`

## Returns

String representation of the AST node.

## Options

- `:parentheses` controls parentheses generation:
  - `:minimal` - only add parentheses when necessary for precedence
  - `:explicit` - add parentheses around all comparisons
  - `:none` - never add parentheses (may change meaning!)

- `:spacing` controls whitespace:
  - `:normal` - standard spacing: "limit > 85"
  - `:compact` - minimal spacing: "limit>85"
  - `:verbose` - extra spacing: "limit  >  85"

---

*Consult [api-reference.md](api-reference.md) for complete listing*
