(**************************************************************************)
(*                                                                        *)
(*                   Copyright (c) 2022 John Jackson.                     *)
(*                                                                        *)
(*  This Source Code Form is subject to the terms of the Mozilla Public   *)
(*  License, v. 2.0. If a copy of the MPL was not distributed with this   *)
(*  file, You can obtain one at http://mozilla.org/MPL/2.0/.              *)
(*                                                                        *)
(**************************************************************************)

(** Define the untyped abstract syntax tree to be generated by the {!Parser}. *)

type 'a assoc = (Loc.t * string * 'a) list
type 'a assoc_nonempty = (Loc.t * string * 'a) Nonempty.t

type tag =
  | Tag_int of Loc.t * int
  | Tag_bool of Loc.t * int
  | Tag_string of Loc.t * string

type 'a value = Tag of tag | Value of 'a
type 'a record = 'a value assoc_nonempty
type row = Loc.t * [ `Closed | `Open ]

type ty =
  | Ty_named of Loc.t * string
  | Ty_nullable of ty
  | Ty_list of ty
  | Ty_dict of ty
  | Ty_enum_int of int Nonempty.t * row
  | Ty_enum_bool of int Nonempty.t
  | Ty_enum_string of string Nonempty.t * row
  | Ty_record of (Loc.t * ty record) Nonempty.t * row
  | Ty_tuple of ty list

type prop = { loc : Loc.t; name : string; ty : ty }
type interface = prop list
type trim = No_trim | Trim
type escape = No_escape | Escape
type echo_format = Fmt_string | Fmt_int | Fmt_float | Fmt_bool

(** The echo syntax is essentially a subset of the pattern syntax, one which
    only allows strings, variables, and record field access. *)

type echo =
  | Echo_var of Loc.t * string
  | Echo_string of Loc.t * string
  | Echo_field of echo * string

type pat =
  | Var of Loc.t * string
  | Bool of Loc.t * int
  | Int of Loc.t * int
  | Float of Loc.t * float
  | String of Loc.t * string
  | Nullable of Loc.t * pat option
  | Enum_string of Loc.t * string
  | Enum_int of Loc.t * int
  | List of Loc.t * pat list * pat option
  | Tuple of Loc.t * pat list
  | Record of Loc.t * pat record
  | Dict of Loc.t * pat assoc
  | Block of Loc.t * t
  | Field of Loc.t * pat * string

and node =
  | Text of string * trim * trim
  | Echo of (echo_format * echo) list * echo_format * echo * escape
  | Match of Loc.t * pat Nonempty.t * case Nonempty.t
  | Map_list of Loc.t * pat * case Nonempty.t
  | Map_dict of Loc.t * pat * case Nonempty.t
  | Component of Loc.t * string * string * pat assoc
  | Interface of Loc.t * interface
  | Comment of string

and case = { pats : (Loc.t * pat Nonempty.t) Nonempty.t; nodes : t }
and t = node list

val dummy_var : pat
(** A variable that is always ignored. *)

val echo_format_to_sexp : echo_format -> Sexp.t
val escape_to_sexp : escape -> Sexp.t
val to_sexp : t -> Sexp.t
val pp_tag : Format.formatter -> tag -> unit
val pp_pat : Format.formatter -> pat -> unit
