aboutsummaryrefslogtreecommitdiffstats
path: root/lib/mininix/mininix2nix.ml
blob: efbc42a0ebbc32d6fcd3226a8fd7f80a5d7b00f5 (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 Conv
open Core

(* [or] is not a 'strong' keyword. That means that 'it depends' whether it is
   identified as such. In the context of the left-hand side of an attribute, it
   is not recognized as such. *)
let strong_keywords =
  [ "with"; "rec"; "let"; "in"; "inherit"; "if"; "then"; "else"; "assert" ]

let id_re = Str.regexp {|^[A-Za-z_]+[A-Za-z0-9'_-]*$|}

let is_simple_id s =
  Str.string_match id_re s 0
  && not (List.exists strong_keywords ~f:(String.( = ) s))

let thunk_map_to_map tm =
  Extraction.thunk_map_fold
    (fun k t -> Map.add_exn ~key:(String.of_char_list k) ~data:t)
    (Map.empty (module String))
    tm

let from_lit l =
  match l with
  | Extraction.LitString s -> Nix.Ast.Val (Nix.Ast.Str (str s, []))
  | Extraction.LitNull -> Nix.Ast.Id "null"
  | Extraction.LitBool b -> Nix.Ast.Id (if b then "true" else "false")
  | Extraction.LitNum x ->
      Nix.Ast.Val
        (match x with
        | Extraction.NInt x -> Nix.Ast.Int (x |> Extraction.string_of_Z |> str)
        | Extraction.NFloat x ->
            Nix.Ast.Float (Printf.sprintf "%g" (float_from_flocq x)))

let rec from_val = function
  | Extraction.VClo _ | Extraction.VCloMatch _ -> Nix.Ast.Id "<CODE>"
  | Extraction.VLit l -> from_lit l
  | Extraction.VAttr bs ->
      let bs =
        thunk_map_to_map bs
        |> Map.to_alist ~key_order:`Increasing
        |> List.map ~f:(fun (x, t) ->
               let lhs =
                 if is_simple_id x then Nix.Ast.Id x
                 else Nix.Ast.Val (Nix.Ast.Str (x, []))
               in
               Nix.Ast.AttrPath ([ lhs ], from_thunk t))
      in
      Nix.Ast.Val (Nix.Ast.AttSet (Nix.Ast.Nonrec, bs))
  | Extraction.VList ts -> Nix.Ast.Val (Nix.Ast.List List.(ts >>| from_thunk))

and from_thunk = function
  | Extraction.Thunk (_, ELit l) -> from_lit l
  | Extraction.Thunk _ | Extraction.Indirect _ -> Nix.Ast.Id "<CODE>"
  | Extraction.Forced v -> from_val v