(** Default implementation which does nothing.

    This module is expected to be used when you only need to implement an
    analyze over a limited part of the whole syntax. *)

open StdLabels
module S = Qsp_syntax.S
module T = Qsp_syntax.T
module Report = Qsp_syntax.Report

module Expression (T' : sig
  type t

  val default : t
end) =
struct
  (** Describe a variable, using the name in capitalized text, and an optionnal
      index.

      If missing, the index should be considered as [0]. *)

  type t' = T'.t

  let ident : (S.pos, T'.t) S.variable -> T'.t = fun _ -> T'.default

  (*
        Basic values, text, number…
   *)

  let integer : S.pos -> string -> T'.t = fun _ _ -> T'.default
  let literal : S.pos -> T'.t T.literal list -> T'.t = fun _ _ -> T'.default

  (** Call a function. The functions list is hardcoded in lib/lexer.mll *)
  let function_ : S.pos -> T.function_ -> T'.t list -> T'.t =
   fun _ _ _ -> T'.default

  (** Unary operator like [-123] or [+'Text']*)
  let uoperator : S.pos -> T.uoperator -> T'.t -> T'.t = fun _ _ _ -> T'.default

  (** Binary operator, for a comparaison, or an operation *)
  let boperator : S.pos -> T.boperator -> T'.t -> T'.t -> T'.t =
   fun _ _ _ _ -> T'.default
end

module Instruction (Expression : sig
  type t'
end) (T : sig
  type t

  val default : t
  val fold : t Seq.t -> t
end) =
struct
  let call : S.pos -> Qsp_syntax.T.keywords -> Expression.t' list -> T.t =
   fun _ _ _ -> T.default

  let location : S.pos -> string -> T.t =
   fun position name ->
    ignore position;
    ignore name;
    T.default

  let comment : S.pos -> T.t =
   fun position ->
    ignore position;
    T.default

  let expression : Expression.t' -> T.t =
   fun expr ->
    ignore expr;
    T.default

  let map_clause : (Expression.t', T.t) S.clause -> T.t Seq.t =
   fun (_, _, els) -> List.to_seq els

  let if_ :
      S.pos ->
      (Expression.t', T.t) S.clause ->
      elifs:(Expression.t', T.t) S.clause list ->
      else_:(S.pos * T.t list) option ->
      T.t =
   fun pos clause ~elifs ~else_ ->
    ignore pos;

    let seq = List.to_seq (clause :: elifs) |> Seq.flat_map map_clause in

    let seq =
      match else_ with
      | None -> seq
      | Some (_, ts) -> Seq.append seq (List.to_seq ts)
    in
    T.fold seq

  let act : S.pos -> label:Expression.t' -> T.t list -> T.t =
   fun pos ~label instructions ->
    ignore pos;
    ignore label;
    T.fold (List.to_seq instructions)

  let assign :
      S.pos ->
      (S.pos, Expression.t') S.variable ->
      Qsp_syntax.T.assignation_operator ->
      Expression.t' ->
      T.t =
   fun _ _ _ _ -> T.default
end