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
open Catala_utils
type 'ast plugin_apply_fun_typ =
source_file:Pos.input_file ->
output_file:string option ->
scope:string option ->
'ast ->
Scopelang.Dependency.TVertex.t list ->
unit
type 'ast gen = {
name : string;
extension : string;
apply : 'ast plugin_apply_fun_typ;
}
type t =
| Lcalc of Shared_ast.untyped Lcalc.Ast.program gen
| Scalc of Scalc.Ast.program gen
let name = function Lcalc { name; _ } | Scalc { name; _ } -> name
let backend_plugins : (string, t) Hashtbl.t = Hashtbl.create 17
let register t =
Hashtbl.replace backend_plugins (String.lowercase_ascii (name t)) t
module PluginAPI = struct
let register_lcalc ~name ~extension apply =
register (Lcalc { name; extension; apply })
let register_scalc ~name ~extension apply =
register (Scalc { name; extension; apply })
end
let find name = Hashtbl.find backend_plugins (String.lowercase_ascii name)
let load_file f =
try
Dynlink.loadfile f;
Cli.debug_print "Plugin %S loaded" f
with e ->
Errors.format_warning "Could not load plugin %S: %s" f
(Printexc.to_string e)
let rec load_dir d =
let dynlink_exts =
if Dynlink.is_native then [".cmxs"] else [".cmo"; ".cma"]
in
Array.iter
(fun f ->
if f.[0] = '.' then ()
else
let f = Filename.concat d f in
if Sys.is_directory f then load_dir f
else if List.exists (Filename.check_suffix f) dynlink_exts then
load_file f)
(Sys.readdir d)