package GT

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

Source file foldl.ml

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
(*
 * Generic transformers: plugins.
 * Copyright (C) 2016-2019
 *   Dmitrii Kosarev aka Kakadu
 * St.Petersburg State University, JetBrains Research
 *)

(** {i Foldl} plugin: fold all values in a type.

    Essentially is a stub that chains inherited attribute thorough all values
    in the value

    For type declaration [type ('a,'b,...) typ = ...] it will create a transformation
    function with type

    [('s -> 'a -> 's) ->
     ('s -> 'b -> 's) ->
     ... ->
     's -> ('a,'b,...) typ -> 's ]
*)

open Base
open Ppxlib
open Printf
open GTCommon
open HelpersBase

let trait_name = "foldl"

module Make(AstHelpers : GTHELPERS_sig.S) = struct
open AstHelpers
module P = Plugin.Make(AstHelpers)

let trait_name = trait_name
let make_dest_param_names ps =
  map_type_param_names ps ~f:(Printf.sprintf "%s_2")

class g initial_args tdecls = object(self: 'self)
  inherit P.with_inherited_attr initial_args tdecls

  method trait_name = trait_name

  method syn_of_param ~loc s = Typ.var ~loc "syn"
  method inh_of_main  ~loc tdecl = self#syn_of_main ~loc tdecl
  method syn_of_main  ~loc ?in_class tdecl = self#syn_of_param ~loc "dummy"

  method inh_of_param ~loc tdecl _ = self#syn_of_param ~loc "dummy"

  method plugin_class_params ~loc typs ~typname =
    (List.map typs ~f:Typ.from_caml) @
    [ Typ.var ~loc "syn"
    ; Typ.var ~loc @@ Naming.make_extra_param typname ]

  (* new type of trasfomation function is 'syn -> old_type *)
  method! make_typ_of_class_argument: 'a . loc:loc -> type_declaration ->
    (Typ.t -> 'a -> 'a) ->
    string -> (('a -> 'a) -> 'a -> 'a) -> 'a -> 'a =
    fun ~loc tdecl chain name k ->
      let subj_t = Typ.var ~loc name in
      let syn_t = self#syn_of_param ~loc name in
      let inh_t = self#inh_of_param ~loc tdecl name in
      k @@ chain (Typ.arrow ~loc inh_t @@ Typ.arrow ~loc subj_t syn_t)

  method join_args ~loc do_typ ~init (xs: (string * core_type) list) =
    List.fold_left ~f:(fun acc (name,typ) ->
        Exp.app_list ~loc
          (do_typ typ)
          [ acc; Exp.sprintf ~loc "%s" name]
        )
        ~init
        xs

  method on_tuple_constr ~loc ~is_self_rec ~mutual_decls ~inhe tdecl constr_info args =
    self#join_args ~loc ~init:inhe
        (self#do_typ_gen ~loc ~is_self_rec ~mutual_decls tdecl)
        args

  method on_record_declaration ~loc ~is_self_rec ~mutual_decls tdecl labs =
    (* TODO: introduce fresh pattern names here *)
    let pat = Pat.record ~loc @@
      List.map labs ~f:(fun l ->
          (Lident l.pld_name.txt, Pat.var ~loc l.pld_name.txt)
        )
    in
    let methname = sprintf "do_%s" tdecl.ptype_name.txt in
    [ Cf.method_concrete ~loc methname @@
      Exp.fun_list ~loc
        [ Pat.sprintf ~loc "inh"; pat] @@
        self#join_args ~loc ~init:(Exp.ident ~loc "inh")
          (self#do_typ_gen ~loc ~is_self_rec ~mutual_decls tdecl)
          (List.map labs ~f:(fun l -> (l.pld_name.txt, l.pld_type)))

    ]

  method! on_record_constr ~loc ~is_self_rec ~mutual_decls ~inhe tdecl _info bindings labs =
    assert Int.(List.length labs > 0);

    Exp.fun_list ~loc (List.map bindings ~f:(fun (s,_,_) -> Pat.sprintf ~loc "%s" s)) @@
    self#join_args ~loc ~init:inhe
      (self#do_typ_gen ~loc ~is_self_rec ~mutual_decls tdecl)
      (List.map bindings ~f:(fun (name,_,typ) -> (name, typ)))

end
let create = (new g :> P.plugin_constructor)

end

let register () =
  Expander.register_plugin trait_name (module Make: Plugin_intf.MAKE)

let () = register ()
OCaml

Innovation. Community. Security.