aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mininix/import.ml
blob: ca1bfb540ca120ab2676b2f4c301fc831e6bca1d (about) (plain) (blame)
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
open Core

exception ImportError of string

type tree = { filename : string; deps : forest }
and forest = tree list

let provide (imports : (string * Extraction.coq_val) list) =
  let imports_set =
    Extraction.(
      VAttr
        (List.fold imports ~init:thunk_map_empty ~f:(fun attrs (filename, v) ->
             thunk_map_insert (Conv.chlist filename) (Forced v) attrs)))
  in
  let make_env =
    Extraction.(
      env_insert_abs (Conv.chlist "imports") (Forced imports_set) env_empty)
  in
  Extraction.(
    VClo
      ( Conv.chlist "path",
        make_env,
        EBinOp
          ( SelectAttrOp,
            EId (Conv.chlist "imports", None),
            EId (Conv.chlist "path", None) ) ))

let make_env (imports : (string * Extraction.coq_val) list) =
  Extraction.(
    env_insert_abs (Conv.chlist "import") (Forced (provide imports)) env_empty)

let rec import trees : (string * Extraction.coq_val) list =
  List.map trees ~f:(fun { filename; deps } ->
      let data = In_channel.read_all filename in
      Nix.parse ~filename data |> Nix.elaborate |> Nix2mininix.from_nix
      |> Builtins.apply_prelude
      |> Run.interp ~fuel:`Unlimited ~mode:`Shallow
           ~env:(make_env (import deps))
      |> function
      | Res (Some v) -> (filename, v)
      | Res None ->
          raise
            (ImportError
               (sprintf "Could not import %s: Failed to evaluate" filename))
      | NoFuel -> assert false)

let rec tree_map ~(f : string -> string) { filename; deps } =
  { filename = f filename; deps = forest_map ~f deps }

and forest_map ~(f : string -> string) trees = List.map ~f:(tree_map ~f) trees

(* [relative_to] must be an absolute path *)
let materialize forest ~relative_to : (string * Extraction.coq_val) list =
  forest_map forest ~f:(Filename.to_absolute_exn ~relative_to) |> import