aboutsummaryrefslogtreecommitdiff
path: root/lib/syntax/nested_strings.ml
blob: c7b0b83a88332a0d008aeb1ca5acb6f994727d29 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
open StdLabels

let identifier = "escaped_string"
let description = "Check for unnecessary use of expression encoded in string"
let active = ref true

module Expression : S.Expression with type t' = Report.t list = struct
  type t = Report.t list * Type_of.Expression.t
  type t' = Report.t list

  let get_type t = Type_of.Expression.v t |> Type_of.get_type
  let v : t -> t' = Stdlib.fst

  (** Identify the expressions reprented as string. That’s here that the report
      are added. 

      All the rest of the module only push thoses warning to the top level. *)
  let literal : S.pos -> t T.literal list -> t =
   fun pos content ->
    let type_of =
      List.map content ~f:(function
        | T.Text _ as text -> text
        | T.Expression expr -> T.Expression (List.map ~f:snd expr))
      |> Type_of.Expression.literal pos
    in

    match content with
    | [ T.Expression [ (_, t') ]; T.Text "" ] -> (
        match get_type t' with
        | Type_of.Helper.Integer -> ([], type_of)
        | _ ->
            let msg = Report.debug pos "This expression can be simplified" in
            ([ msg ], type_of))
    | _ -> ([], type_of)

  let ident : (S.pos, t) S.variable -> t =
   fun { pos; name : string; index : t option } ->
    match index with
    | None ->
        let type_ = Type_of.Expression.ident { pos; name; index = None } in
        ([], type_)
    | Some (v, t') ->
        let type_ = Type_of.Expression.ident { pos; name; index = Some t' } in
        (v, type_)

  let integer : S.pos -> string -> t =
   fun pos t -> ([], Type_of.Expression.integer pos t)

  let function_ : S.pos -> T.function_ -> t list -> t =
   fun pos f expressions ->
    let r, t = List.split expressions in

    let type_of = Type_of.Expression.function_ pos f t in
    (List.concat r, type_of)

  let uoperator : S.pos -> T.uoperator -> t -> t =
   fun pos op (r, expr1) -> (r, Type_of.Expression.uoperator pos op expr1)

  let boperator : S.pos -> T.boperator -> t -> t -> t =
   fun pos op (r1, expr1) (r2, expr2) ->
    (r1 @ r2, Type_of.Expression.boperator pos op expr1 expr2)
end

module Instruction :
  S.Instruction with type t' = Report.t list and type expression = Expression.t' =
struct
  type t = Report.t list
  (** Internal type used in the evaluation *)

  type t' = t

  let v : t -> t' = Fun.id

  type expression = Expression.t'

  let call : S.pos -> T.keywords -> expression list -> t =
   fun pos k exprs ->
    ignore pos;
    ignore k;
    List.concat exprs

  let location : S.pos -> string -> t = fun _ _ -> []
  let comment : S.pos -> t = fun _ -> []
  let expression : expression -> t = Fun.id

  let act : S.pos -> label:expression -> t list -> t =
   fun pos ~label instructions ->
    ignore pos;
    List.concat (label :: instructions)

  let fold_clause : (expression, t) S.clause -> t =
   fun (_pos1, expression, ts) -> List.concat (expression :: ts)

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

    let init =
      match else_ with
      | None -> fold_clause clause
      | Some (_, ts) -> List.rev_append (fold_clause clause) (List.concat ts)
    in

    List.fold_left elifs ~init ~f:(fun t clause ->
        List.rev_append (fold_clause clause) t)

  let assign :
      S.pos ->
      (S.pos, expression) S.variable ->
      T.assignation_operator ->
      expression ->
      t =
   fun pos variable op expression ->
    ignore pos;
    ignore op;
    match variable.index with
    | None -> expression
    | Some v -> List.rev_append v expression
end

module Location = struct
  type t = Report.t list
  type instruction = Instruction.t'

  let v = Fun.id

  let location : S.pos -> instruction list -> t =
   fun pos intructions ->
    ignore pos;
    List.concat intructions
end