aboutsummaryrefslogtreecommitdiff
path: root/lib/expression/sym.ml
blob: 0360e8e4c1e50337cb1c935a6eab859da762dc33 (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
(** The signature for an expression analyzer.

    Every element is mapped to a function, using the tagless final pattern.

 *)
module type SYM_EXPR = sig
  type 'a repr
  type 'a obs
  type 'a path_repr

  val empty : unit -> 'a repr
  val expr : 'a repr -> 'a repr
  val literal : string -> 'a repr
  val integer : string -> 'a repr
  val path : 'a path_repr -> 'a -> 'a repr
  val concat : 'a repr list -> 'a repr
  val window : 'a repr T.window -> 'a repr list -> 'a repr list -> 'a repr
  val nvl : 'a repr list -> 'a repr
  val join : string -> 'a repr list -> 'a repr
  val boperator : T.binary_operator -> 'a repr -> 'a repr -> 'a repr
  val gequality : T.binary_operator -> 'a repr -> 'a repr list -> 'a repr
  val funct : string -> 'a repr list -> 'a repr
  val function' : T.funct -> 'a repr list -> 'a repr
  val observe : 'a repr -> 'a obs
end

module type SYM_CHUNK = sig
  include SYM_EXPR

  val group : 'a repr list -> 'a repr
  val arguments : 'a repr list -> 'a repr
end

open StdLabels

module M (Expr : SYM_EXPR) = struct
  let rec eval : path_repr:'a Expr.path_repr -> 'a T.t -> 'c Expr.repr =
   fun ~path_repr t ->
    match t with
    | T.Expr expr -> Expr.expr (eval ~path_repr expr)
    | T.Empty -> Expr.empty ()
    | T.Literal s -> Expr.literal s
    | T.Integer i -> Expr.integer i
    | T.Concat elems -> Expr.concat (List.map elems ~f:(eval ~path_repr))
    | T.Function (name, args) ->
        Expr.funct name (List.map args ~f:(eval ~path_repr))
    | T.Function' (name, args) ->
        Expr.function' name (List.map args ~f:(eval ~path_repr))
    | T.Nvl elems -> Expr.nvl (List.map elems ~f:(eval ~path_repr))
    | T.Join (sep, args) -> Expr.join sep (List.map args ~f:(eval ~path_repr))
    | T.Window (name, group, sort) ->
        Expr.window
          (eval_window ~path_repr name)
          (List.map group ~f:(eval ~path_repr))
          (List.map sort ~f:(eval ~path_repr))
    | T.BOperator (op, arg1, arg2) ->
        Expr.boperator op (eval ~path_repr arg1) (eval ~path_repr arg2)
    | T.GEquality (op, arg1, arg2) ->
        Expr.gequality op (eval ~path_repr arg1)
          (List.map arg2 ~f:(eval ~path_repr))
    | T.Path p -> Expr.path path_repr p

  and eval_window :
      path_repr:'a Expr.path_repr -> 'a T.t T.window -> 'a Expr.repr T.window =
   fun ~path_repr -> function
    | Min a -> Min (eval ~path_repr a)
    | Max a -> Max (eval ~path_repr a)
    | Counter -> Counter
    | Previous a -> Previous (eval ~path_repr a)
    | Sum a -> Sum (eval ~path_repr a)
end