package acgtk

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

Source file environment.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
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
(**************************************************************************)
(*                                                                        *)
(*                 ACG development toolkit                                *)
(*                                                                        *)
(*                  Copyright 2008-2023 INRIA                             *)
(*                                                                        *)
(*  More information on "https://acg.loria.fr/"                     *)
(*  License: CeCILL, see the LICENSE file or "http://www.cecill.info"     *)
(*  Authors: see the AUTHORS file                                         *)
(*                                                                        *)
(*                                                                        *)
(*                                                                        *)
(*                                                                        *)
(*                                                                        *)
(**************************************************************************)

open UtilsLib
open Signature
open Acg_lexicon

module Environment = struct
  module Env = Utils.StringMap

  type to_be_dumped = bool
  type entry = Signature of Data_Signature.t | Lexicon of Data_Lexicon.t
  type dumped_entry = Signature_d of Data_Signature.t | Lexicon_d of Data_Lexicon.dumped_t

  module Dep = DependencyManager.Make (struct
    type t = string

    let compare e1 e2 = String.compare e1 e2
  end)

  type t = {
    map : (entry * to_be_dumped) Env.t;
    sig_number : int;
    lex_number : int;
    dependencies : Dep.t;
  }

  type dumped_t= {
    dumped_filename : string;
    dumped_map : dumped_entry Env.t;
    dumped_sig_number : int;
    dumped_lex_number : int;
    dumped_dependencies : Dep.t;
  }

  
  let empty =
    {
      map = Env.empty;
      sig_number = 0;
      lex_number = 0;
      dependencies = Dep.empty;
    }

  let update_dependencies lex m =
    match Data_Lexicon.get_dependencies lex with
    | Data_Lexicon.Signatures (s1, s2) ->
        Dep.add_dependency (fst (Data_Lexicon.name lex)) s1
          (Dep.add_dependency (fst (Data_Lexicon.name lex)) s2 m)
    | Data_Lexicon.Lexicons deps ->
      List.fold_left
        (fun acc l -> Dep.add_dependency (fst (Data_Lexicon.name lex)) l acc)
        m
        deps

  let insert ?(overwrite = false) d ~to_be_dumped:dump e =
    match d with
    | Signature s ->
        let name, (p1, p2) = Data_Signature.name s in
        if (not (Env.mem name e.map)) || overwrite then
          {
            e with
            map = Env.add name (d, dump) e.map;
            sig_number = e.sig_number + 1;
          }
        else
          Errors.(EnvironmentErrors.emit (Environment_l.DuplicatedEntry name) ~loc:(p1, p2))
    | Lexicon l ->
        let name, (p1, p2) = Data_Lexicon.name l in
        if (not (Env.mem name e.map)) || overwrite then
          {
            e with
            map = Env.add name (d, dump) e.map;
            lex_number = e.lex_number + 1;
            dependencies = update_dependencies l e.dependencies;
          }
        else
          Errors.(EnvironmentErrors.emit (Environment_l.DuplicatedEntry name) ~loc:(p1, p2))

  let iter f { map = e; _ } = Env.iter (fun _ (d, _) -> f d) e
  let fold f a { map = e; _ } = Env.fold (fun _ (d, _) acc -> f d acc) e a
  let sig_number { sig_number = n; _ } = n
  let lex_number { lex_number = n; _ } = n

  let prepare_dump ?(force=false) ~filename e =
      Env.fold
        (fun name (entry, d) acc ->
           match entry, d || force with
           | _, false -> acc
           | Signature sg, true ->
             {acc with
              dumped_map = Env.add name (Signature_d sg) acc.dumped_map ;
              dumped_sig_number = acc.dumped_sig_number + 1}
           | Lexicon l, true ->
             {acc with
              dumped_map = Env.add name (Lexicon_d (Data_Lexicon.prepare_dump l)) acc.dumped_map ;
              dumped_lex_number = acc.dumped_lex_number + 1})
        e.map
        {dumped_map = Env.empty;
         dumped_filename = filename;
         dumped_sig_number = 0;
         dumped_lex_number = 0;
         dumped_dependencies = e.dependencies}

  let recover_from_dump ~current_env e =
    let get_sig ~lex:lex env name =
      match Env.find_opt name env.map with
      | Some (Signature sg, _) -> sg
      | _ ->
        (match Env.find_opt name current_env.map with
         | Some (Signature sg, _) -> sg
         | _ -> Errors.(LexiconErrors.emit (Lexicon_l.UnavailableSignature (lex, name, e.dumped_filename)))) in
    let new_env, lexicons =
      Env.fold
        (fun name entry (acc, lexs) ->
           match entry with
           | Signature_d sg ->
             {acc with
              map = Env.add name (Signature sg, false) acc.map ;
              sig_number = acc.sig_number + 1},
             lexs
           | Lexicon_d lex ->
             {acc with
              lex_number = acc.lex_number + 1},
             (name, lex)::lexs)
        e.dumped_map
        ({map = Env.empty;
          sig_number = 0;
          lex_number = 0;
          dependencies = e.dumped_dependencies},
         []) in
    List.fold_left
      (fun acc (name, lex) ->
         {acc with    
          map = Env.add name (Lexicon (Data_Lexicon.recover_from_dump ~filename:e.dumped_filename ~get_sig:(get_sig ~lex:(Data_Lexicon.name_of_dumped lex) new_env) lex), false) acc.map})
      new_env
      lexicons
      
  let append ?(overwrite = false) e1 e2 =
    let erased_sig = ref 0 in
    let erased_lex = ref 0 in
    let e2 = recover_from_dump ~current_env:e1 e2 in
    let new_map =
      Env.merge
        (fun _ v1 v2 ->
          match (v1, v2, overwrite) with
          | None, None, _ -> None
          | None, Some v, _ -> Some v
          | Some v, None, _ -> Some v
          | Some (Lexicon _, _), Some v2, true ->
              let () = erased_lex := !erased_lex + 1 in
              Some v2
          | Some (Signature _, _), Some v2, true ->
              let () = erased_sig := !erased_sig + 1 in
              Some v2
          | Some (_, _), Some (v2, _), false -> (
              match v2 with
              | Signature sg ->
                  let name, loc = Data_Signature.name sg in
                  Errors.(EnvironmentErrors.emit (Environment_l.DuplicatedEntry name) ~loc)
              | Lexicon lex ->
                  let name, loc = Data_Lexicon.name lex in
                  Errors.(EnvironmentErrors.emit (Environment_l.DuplicatedEntry name) ~loc)))
        e1.map e2.map
    in
    {
      map = new_map;
      sig_number = e1.sig_number + e2.sig_number - !erased_sig;
      lex_number = e1.lex_number + e2.lex_number - !erased_lex;
      dependencies = Dep.merge e1.dependencies e2.dependencies;
    }

    
  let get entry { map = e; _ } loc =
    try
      let data, _ = Env.find entry e in
      data
    with Not_found -> Errors.(EnvironmentErrors.emit (Environment_l.EntryNotFound entry) ~loc)

  let get_signature s { map = e; _ } loc =
    let data = try
      let data, _ = Env.find s e in
      data
    with Not_found -> Errors.(EnvironmentErrors.emit (Environment_l.EntryNotFound s) ~loc) in
    match data with
    | Signature s -> s
    | _ -> Errors.(EnvironmentErrors.emit (Environment_l.NotASignature s) ~loc)

  let get_lexicon l { map = e; _ } loc =
    let data = try
      let data, _ = Env.find l e in
      data
    with Not_found -> Errors.(EnvironmentErrors.emit (Environment_l.EntryNotFound l) ~loc) in
    match data with
    | Lexicon l -> l
    | _ -> Errors.(EnvironmentErrors.emit (Environment_l.NotALexicon l) ~loc)

  let get_opt s { map = e; _ } =
    try
      let data, _ = Env.find s e in
      Some data
    with Not_found -> None

  let list_signatures { map = e; _ } =
    Seq.fold_left (fun res (name, (entry, _)) -> match entry with | Signature _ -> name :: res | _ -> res) [] (Env.to_seq e)

  let list_lexicons { map = e; _ } =
    Seq.fold_left (fun res (name, (entry, _)) -> match entry with | Lexicon _ -> name :: res | _ -> res) [] (Env.to_seq e)

  let magic e =
    {
      e with
      map =
        Env.map
          (fun v ->
             match v with
             | Signature _, _ -> v
             | Lexicon l, b when (Data_Lexicon.has_magic l) = Data_Lexicon.Available_wo_magic ->
               (Lexicon (Data_Lexicon.magic l), b)
             | Lexicon _, _ -> v)
          e.map;
    }

  exception Sig of Data_Signature.t

  let choose_signature { map = e; _ } =
    try
      let () =
        Env.fold
          (fun _ c a ->
            match c with Signature s, _ -> raise (Sig s) | Lexicon _, _ -> a)
          e ()
      in
      None
    with Sig s -> Some s
end
OCaml

Innovation. Community. Security.