Merge pull request #1170 from rgrinberg/invert-sexp-stdune

Invert sexp stdune
This commit is contained in:
Rudi Grinberg 2018-08-23 16:37:13 +03:00 committed by GitHub
commit 64755f8826
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
231 changed files with 2803 additions and 2517 deletions

View File

@ -1,3 +1,4 @@
open! Stdune
open Dune open Dune
open Import open Import
open Cmdliner open Cmdliner
@ -985,11 +986,11 @@ let rules =
in in
Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules -> Build_system.build_rules setup.build_system ~request ~recursive >>= fun rules ->
let sexp_of_action action = let sexp_of_action action =
Action.for_shell action |> Action.For_shell.sexp_of_t Action.for_shell action |> Action.For_shell.dgen
in in
let print oc = let print oc =
let ppf = Format.formatter_of_out_channel oc in let ppf = Format.formatter_of_out_channel oc in
Sexp.prepare_formatter ppf; Dsexp.prepare_formatter ppf;
Format.pp_open_vbox ppf 0; Format.pp_open_vbox ppf 0;
if makefile_syntax then begin if makefile_syntax then begin
List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> List.iter rules ~f:(fun (rule : Build_system.Rule.t) ->
@ -1000,25 +1001,25 @@ let rules =
(fun ppf -> (fun ppf ->
Path.Set.iter rule.deps ~f:(fun dep -> Path.Set.iter rule.deps ~f:(fun dep ->
Format.fprintf ppf "@ %s" (Path.to_string dep))) Format.fprintf ppf "@ %s" (Path.to_string dep)))
Sexp.pp_split_strings (sexp_of_action rule.action)) Dsexp.pp_split_strings (sexp_of_action rule.action))
end else begin end else begin
List.iter rules ~f:(fun (rule : Build_system.Rule.t) -> List.iter rules ~f:(fun (rule : Build_system.Rule.t) ->
let sexp = let sexp =
let paths ps = let paths ps =
Sexp.To_sexp.list Path.sexp_of_t (Path.Set.to_list ps) Dsexp.To_sexp.list Path_dsexp.dgen (Path.Set.to_list ps)
in in
Sexp.To_sexp.record ( Dsexp.To_sexp.record (
List.concat List.concat
[ [ "deps" , paths rule.deps [ [ "deps" , paths rule.deps
; "targets", paths rule.targets ] ; "targets", paths rule.targets ]
; (match rule.context with ; (match rule.context with
| None -> [] | None -> []
| Some c -> ["context", | Some c -> ["context",
Sexp.atom_or_quoted_string c.name]) Dsexp.atom_or_quoted_string c.name])
; [ "action" , sexp_of_action rule.action ] ; [ "action" , sexp_of_action rule.action ]
]) ])
in in
Format.fprintf ppf "%a@," Sexp.pp_split_strings sexp) Format.fprintf ppf "%a@," Dsexp.pp_split_strings sexp)
end; end;
Format.pp_print_flush ppf (); Format.pp_print_flush ppf ();
Fiber.return () Fiber.return ()
@ -1472,7 +1473,7 @@ let printenv =
Build_system.do_build setup.build_system ~request Build_system.do_build setup.build_system ~request
>>| fun l -> >>| fun l ->
let pp ppf = Format.fprintf ppf "@[<v1>(@,@[<v>%a@]@]@,)" let pp ppf = Format.fprintf ppf "@[<v1>(@,@[<v>%a@]@]@,)"
(Format.pp_print_list (Sexp.pp Dune)) in (Format.pp_print_list (Dsexp.pp Dune)) in
match l with match l with
| [(_, env)] -> | [(_, env)] ->
Format.printf "%a@." pp env Format.printf "%a@." pp env

View File

@ -36,7 +36,7 @@ let dirs =
; "src/xdg" , Some "Xdg" ; "src/xdg" , Some "Xdg"
; "src/ocaml-config" , Some "Ocaml_config" ; "src/ocaml-config" , Some "Ocaml_config"
; "vendor/boot" , None ; "vendor/boot" , None
; "src/usexp" , Some "Usexp" ; "src/dsexp" , Some "Dsexp"
; "src" , None ; "src" , None
] ]

View File

@ -1,5 +1,6 @@
open! Stdune
open Import open Import
open Sexp.Of_sexp open Dsexp.Of_sexp
let ignore_loc k ~loc:_ = k let ignore_loc k ~loc:_ = k
@ -15,9 +16,9 @@ end
module Diff_mode = Action_intf.Diff_mode module Diff_mode = Action_intf.Diff_mode
module Make_ast module Make_ast
(Program : Sexp.Sexpable) (Program : Dsexp.Sexpable)
(Path : Sexp.Sexpable) (Path : Dsexp.Sexpable)
(String : Sexp.Sexpable) (String : Dsexp.Sexpable)
(Ast : Action_intf.Ast (Ast : Action_intf.Ast
with type program := Program.t with type program := Program.t
with type path := Path.t with type path := Path.t
@ -25,13 +26,13 @@ module Make_ast
struct struct
include Ast include Ast
let t = let dparse =
let path = Path.t and string = String.t in let path = Path.dparse and string = String.dparse in
Sexp.Of_sexp.fix (fun t -> Dsexp.Of_sexp.fix (fun t ->
sum sum
[ "run", [ "run",
(let%map prog = Program.t (let%map prog = Program.dparse
and args = repeat string and args = repeat String.dparse
in in
Run (prog, args)) Run (prog, args))
; "chdir", ; "chdir",
@ -129,55 +130,53 @@ struct
Diff { optional = false; file1; file2; mode = Binary }) Diff { optional = false; file1; file2; mode = Binary })
]) ])
let rec sexp_of_t : _ -> Sexp.t = let rec dgen =
let path = Path.sexp_of_t and string = String.sexp_of_t in let open Dsexp in
let program = Program.dgen in
let string = String.dgen in
let path = Path.dgen in
function function
| Run (a, xs) -> List (Sexp.unsafe_atom_of_string "run" | Run (a, xs) ->
:: Program.sexp_of_t a :: List.map xs ~f:string) List (atom "run" :: program a :: List.map xs ~f:string)
| Chdir (a, r) -> List [Sexp.unsafe_atom_of_string "chdir" ; | Chdir (a, r) -> List [atom "chdir" ; path a ; dgen r]
path a ; sexp_of_t r] | Setenv (k, v, r) -> List [atom "setenv" ; string k ; string v ; dgen r]
| Setenv (k, v, r) -> List [Sexp.unsafe_atom_of_string "setenv" ;
string k ; string v ; sexp_of_t r]
| Redirect (outputs, fn, r) -> | Redirect (outputs, fn, r) ->
List [ Sexp.atom (sprintf "with-%s-to" (Outputs.to_string outputs)) List [ atom (sprintf "with-%s-to" (Outputs.to_string outputs))
; path fn ; path fn
; sexp_of_t r ; dgen r
] ]
| Ignore (outputs, r) -> | Ignore (outputs, r) ->
List [ Sexp.atom (sprintf "ignore-%s" (Outputs.to_string outputs)) List [ atom (sprintf "ignore-%s" (Outputs.to_string outputs))
; sexp_of_t r ; dgen r
] ]
| Progn l -> List (Sexp.unsafe_atom_of_string "progn" | Progn l -> List (atom "progn" :: List.map l ~f:dgen)
:: List.map l ~f:sexp_of_t)
| Echo xs -> | Echo xs ->
List (Sexp.unsafe_atom_of_string "echo" :: List.map xs ~f:string) List (atom "echo" :: List.map xs ~f:string)
| Cat x -> List [Sexp.unsafe_atom_of_string "cat"; path x] | Cat x -> List [atom "cat"; path x]
| Copy (x, y) -> | Copy (x, y) ->
List [Sexp.unsafe_atom_of_string "copy"; path x; path y] List [atom "copy"; path x; path y]
| Symlink (x, y) -> | Symlink (x, y) ->
List [Sexp.unsafe_atom_of_string "symlink"; path x; path y] List [atom "symlink"; path x; path y]
| Copy_and_add_line_directive (x, y) -> | Copy_and_add_line_directive (x, y) ->
List [Sexp.unsafe_atom_of_string "copy#"; path x; path y] List [atom "copy#"; path x; path y]
| System x -> List [Sexp.unsafe_atom_of_string "system"; string x] | System x -> List [atom "system"; string x]
| Bash x -> List [Sexp.unsafe_atom_of_string "bash"; string x] | Bash x -> List [atom "bash"; string x]
| Write_file (x, y) -> List [Sexp.unsafe_atom_of_string "write-file"; | Write_file (x, y) -> List [atom "write-file"; path x; string y]
path x; string y] | Rename (x, y) -> List [atom "rename"; path x; path y]
| Rename (x, y) -> List [Sexp.unsafe_atom_of_string "rename"; | Remove_tree x -> List [atom "remove-tree"; path x]
path x; path y] | Mkdir x -> List [atom "mkdir"; path x]
| Remove_tree x -> List [Sexp.unsafe_atom_of_string "remove-tree"; path x] | Digest_files paths -> List [atom "digest-files";
| Mkdir x -> List [Sexp.unsafe_atom_of_string "mkdir"; path x]
| Digest_files paths -> List [Sexp.unsafe_atom_of_string "digest-files";
List (List.map paths ~f:path)] List (List.map paths ~f:path)]
| Diff { optional; file1; file2; mode = Binary} -> | Diff { optional; file1; file2; mode = Binary} ->
assert (not optional); assert (not optional);
List [Sexp.unsafe_atom_of_string "cmp"; path file1; path file2] List [atom "cmp"; path file1; path file2]
| Diff { optional = false; file1; file2; mode = _ } -> | Diff { optional = false; file1; file2; mode = _ } ->
List [Sexp.unsafe_atom_of_string "diff"; path file1; path file2] List [atom "diff"; path file1; path file2]
| Diff { optional = true; file1; file2; mode = _ } -> | Diff { optional = true; file1; file2; mode = _ } ->
List [Sexp.unsafe_atom_of_string "diff?"; path file1; path file2] List [atom "diff?"; path file1; path file2]
| Merge_files_into (srcs, extras, target) -> | Merge_files_into (srcs, extras, target) ->
List List
[ Sexp.unsafe_atom_of_string "merge-files-into" [ atom "merge-files-into"
; List (List.map ~f:path srcs) ; List (List.map ~f:path srcs)
; List (List.map ~f:string extras) ; List (List.map ~f:string extras)
; path target ; path target
@ -268,11 +267,12 @@ module Prog = struct
type t = (Path.t, Not_found.t) result type t = (Path.t, Not_found.t) result
let t : t Sexp.Of_sexp.t = Sexp.Of_sexp.map Path.t ~f:Result.ok let dparse : t Dsexp.Of_sexp.t =
Dsexp.Of_sexp.map Path_dsexp.dparse ~f:Result.ok
let sexp_of_t = function let dgen = function
| Ok s -> Path.sexp_of_t s | Ok s -> Path_dsexp.dgen s
| Error (e : Not_found.t) -> Sexp.To_sexp.string e.program | Error (e : Not_found.t) -> Dsexp.To_sexp.string e.program
end end
module type Ast = Action_intf.Ast module type Ast = Action_intf.Ast
@ -283,13 +283,13 @@ module rec Ast : Ast = Ast
module String_with_sexp = struct module String_with_sexp = struct
type t = string type t = string
let t = Sexp.Of_sexp.string let dparse = Dsexp.Of_sexp.string
let sexp_of_t = Sexp.To_sexp.string let dgen = Dsexp.To_sexp.string
end end
include Make_ast include Make_ast
(Prog) (Prog)
(Path) (Path_dsexp)
(String_with_sexp) (String_with_sexp)
(Ast) (Ast)
@ -372,9 +372,19 @@ module Unexpanded = struct
include Make_ast(String_with_vars)(String_with_vars)(String_with_vars)(Uast) include Make_ast(String_with_vars)(String_with_vars)(String_with_vars)(Uast)
let t = module Mapper = Make_mapper(Uast)(Uast)
let remove_locs =
let no_loc_template = String_with_vars.make_text Loc.none "" in
fun t ->
Mapper.map t ~dir:no_loc_template
~f_program:(fun ~dir:_ -> String_with_vars.remove_locs)
~f_path:(fun ~dir:_ -> String_with_vars.remove_locs)
~f_string:(fun ~dir:_ -> String_with_vars.remove_locs)
let dparse =
if_list if_list
~then_:t ~then_:dparse
~else_: ~else_:
(loc >>| fun loc -> (loc >>| fun loc ->
of_sexp_errorf of_sexp_errorf
@ -383,11 +393,11 @@ module Unexpanded = struct
let check_mkdir loc path = let check_mkdir loc path =
if not (Path.is_managed path) then if not (Path.is_managed path) then
Loc.fail loc Errors.fail loc
"(mkdir ...) is not supported for paths outside of the workspace:\n\ "(mkdir ...) is not supported for paths outside of the workspace:\n\
\ %a\n" \ %a\n"
(Sexp.pp Dune) (Dsexp.pp Dune)
(List [Sexp.unsafe_atom_of_string "mkdir"; Path.sexp_of_t path]) (List [Dsexp.unsafe_atom_of_string "mkdir"; Path_dsexp.dgen path])
module Partial = struct module Partial = struct
module Program = Unresolved.Program module Program = Unresolved.Program
@ -538,7 +548,7 @@ module Unexpanded = struct
Chdir (res, partial_expand t ~dir ~map_exe ~f) Chdir (res, partial_expand t ~dir ~map_exe ~f)
| Right fn -> | Right fn ->
let loc = String_with_vars.loc fn in let loc = String_with_vars.loc fn in
Loc.fail loc Errors.fail loc
"This directory cannot be evaluated statically.\n\ "This directory cannot be evaluated statically.\n\
This is not allowed by dune" This is not allowed by dune"
end end
@ -733,7 +743,7 @@ module Infer = struct
match fn with match fn with
| Left fn -> { acc with targets = Path.Set.add acc.targets fn } | Left fn -> { acc with targets = Path.Set.add acc.targets fn }
| Right sw -> | Right sw ->
Loc.fail (String_with_vars.loc sw) Errors.fail (String_with_vars.loc sw)
"Cannot determine this target statically." "Cannot determine this target statically."
let ( +< ) acc fn = let ( +< ) acc fn =
match fn with match fn with

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
module Outputs : module type of struct include Action_intf.Outputs end module Outputs : module type of struct include Action_intf.Outputs end
@ -31,7 +32,7 @@ include Action_intf.Helpers
with type string := string with type string := string
with type t := t with type t := t
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
module For_shell : sig module For_shell : sig
include Action_intf.Ast include Action_intf.Ast
@ -39,7 +40,7 @@ module For_shell : sig
with type path := string with type path := string
with type string := string with type string := string
val sexp_of_t : t Sexp.To_sexp.t val dgen : t Dsexp.To_sexp.t
end end
(** Convert the action to a format suitable for printing *) (** Convert the action to a format suitable for printing *)
@ -72,7 +73,7 @@ module Unexpanded : sig
with type path := String_with_vars.t with type path := String_with_vars.t
with type string := String_with_vars.t with type string := String_with_vars.t
include Sexp.Sexpable with type t := t include Dsexp.Sexpable with type t := t
module Partial : sig module Partial : sig
include Action_intf.Ast include Action_intf.Ast
@ -94,6 +95,8 @@ module Unexpanded : sig
-> map_exe:(Path.t -> Path.t) -> map_exe:(Path.t -> Path.t)
-> f:(Value.t list option String_with_vars.expander) -> f:(Value.t list option String_with_vars.expander)
-> Partial.t -> Partial.t
val remove_locs : t -> t
end end
(** Infer dependencies and targets. (** Infer dependencies and targets.

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Fiber.O open Fiber.O

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
val exec val exec
: targets:Path.Set.t : targets:Path.Set.t

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
module Outputs = struct module Outputs = struct
type t = type t =

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
type 'a t = type 'a t =

View File

@ -1,3 +1,4 @@
open! Stdune
(** Command line arguments specification *) (** Command line arguments specification *)
(** This module implements a small DSL to specify the command line (** This module implements a small DSL to specify the command line

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Dune_file open Dune_file

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
type t type t

View File

@ -1,4 +1,4 @@
open Import open! Stdune
let path_sep = let path_sep =
if Sys.win32 then if Sys.win32 then

View File

@ -1,6 +1,6 @@
(** OCaml binaries *) (** OCaml binaries *)
open Stdune open! Stdune
(** Character used to separate entries in [PATH] and similar (** Character used to separate entries in [PATH] and similar
environment variables *) environment variables *)

View File

@ -1,12 +1,12 @@
open Stdune open! Stdune
type t = type t =
| Exe | Exe
| Object | Object
| Shared_object | Shared_object
let t = let dparse =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
enum enum
[ "exe" , Exe [ "exe" , Exe
; "object" , Object ; "object" , Object
@ -21,7 +21,7 @@ let to_string = function
let pp fmt t = let pp fmt t =
Format.pp_print_string fmt (to_string t) Format.pp_print_string fmt (to_string t)
let sexp_of_t t = let dgen t =
Sexp.unsafe_atom_of_string (to_string t) Dsexp.unsafe_atom_of_string (to_string t)
let all = [Exe; Object; Shared_object] let all = [Exe; Object; Shared_object]

View File

@ -1,15 +1,13 @@
(** Linking modes for binaries *) (** Linking modes for binaries *)
open Stdune open! Stdune
type t = type t =
| Exe | Exe
| Object | Object
| Shared_object | Shared_object
val t : t Sexp.Of_sexp.t include Dsexp.Sexpable with type t := t
val sexp_of_t : t Sexp.To_sexp.t
val all : t list val all : t list

View File

@ -35,7 +35,7 @@ let rec eval_bool t ~dir ~(f : 'a expander) =
begin match f.f ~mode:Single a with begin match f.f ~mode:Single a with
| _, String "true" -> true | _, String "true" -> true
| _, String "false" -> false | _, String "false" -> false
| loc, _ -> Loc.fail loc "This value must be either true or false" | loc, _ -> Errors.fail loc "This value must be either true or false"
end end
| And xs -> List.for_all ~f:(eval_bool ~f ~dir) xs | And xs -> List.for_all ~f:(eval_bool ~f ~dir) xs
| Or xs -> List.exists ~f:(eval_bool ~f ~dir) xs | Or xs -> List.exists ~f:(eval_bool ~f ~dir) xs

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
module Op : sig module Op : sig
type t = type t =

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module Vspec = struct module Vspec = struct
@ -59,8 +60,8 @@ module Repr = struct
| G_evaluated l -> l | G_evaluated l -> l
| G_unevaluated (loc, path, _) -> | G_unevaluated (loc, path, _) ->
Exn.code_error "Build.get_glob_result_exn: got unevaluated" Exn.code_error "Build.get_glob_result_exn: got unevaluated"
[ "loc", Loc.sexp_of_t loc [ "loc", Loc.to_sexp loc
; "path", Path.sexp_of_t path ] ; "path", Path.to_sexp path ]
end end
include Repr include Repr
let repr t = t let repr t = t
@ -130,7 +131,7 @@ let strings p =
let read_sexp p syntax = let read_sexp p syntax =
contents p contents p
>>^ fun s -> >>^ fun s ->
Usexp.parse_string s Dsexp.parse_string s
~lexer:(File_tree.Dune_file.Kind.lexer syntax) ~lexer:(File_tree.Dune_file.Kind.lexer syntax)
~fname:(Path.to_string p) ~mode:Single ~fname:(Path.to_string p) ~mode:Single

View File

@ -1,5 +1,6 @@
(** The build arrow *) (** The build arrow *)
open! Stdune
open! Import open! Import
type ('a, 'b) t type ('a, 'b) t
@ -95,7 +96,7 @@ val lines_of : Path.t -> ('a, string list) t
val strings : Path.t -> ('a, string list) t val strings : Path.t -> ('a, string list) t
(** Load an S-expression from a file *) (** Load an S-expression from a file *)
val read_sexp : Path.t -> Usexp.syntax -> (unit, Sexp.Ast.t) t val read_sexp : Path.t -> Dsexp.syntax -> (unit, Dsexp.Ast.t) t
(** Evaluates to [true] if the file is present on the file system or is the target of a (** Evaluates to [true] if the file is present on the file system or is the target of a
rule. *) rule. *)

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Build.Repr open Build.Repr
@ -82,11 +83,11 @@ let static_deps t ~all_targets ~file_tree =
if Path.Set.is_empty result then begin if Path.Set.is_empty result then begin
match inspect_path file_tree dir with match inspect_path file_tree dir with
| None -> | None ->
Loc.warn loc "Directory %s doesn't exist." Errors.warn loc "Directory %s doesn't exist."
(Path.to_string_maybe_quoted (Path.to_string_maybe_quoted
(Path.drop_optional_build_context dir)) (Path.drop_optional_build_context dir))
| Some Reg -> | Some Reg ->
Loc.warn loc "%s is not a directory." Errors.warn loc "%s is not a directory."
(Path.to_string_maybe_quoted (Path.to_string_maybe_quoted
(Path.drop_optional_build_context dir)) (Path.drop_optional_build_context dir))
| Some Dir -> | Some Dir ->
@ -187,7 +188,7 @@ let targets =
match loop a [], loop b [] with match loop a [], loop b [] with
| [], [] -> acc | [], [] -> acc
| a, b -> | a, b ->
let targets x = Path.Set.sexp_of_t (Target.paths x) in let targets x = Path.Set.to_sexp (Target.paths x) in
Exn.code_error "Build_interpret.targets: cannot have targets \ Exn.code_error "Build_interpret.targets: cannot have targets \
under a [if_file_exists]" under a [if_file_exists]"
[ "targets-a", targets a [ "targets-a", targets a
@ -219,7 +220,7 @@ module Rule = struct
match targets with match targets with
| [] -> | [] ->
begin match loc with begin match loc with
| Some loc -> Loc.fail loc "Rule has no targets specified" | Some loc -> Errors.fail loc "Rule has no targets specified"
| None -> Exn.code_error "Build_interpret.Rule.make: no targets" [] | None -> Exn.code_error "Build_interpret.Rule.make: no targets" []
end end
| x :: l -> | x :: l ->
@ -230,11 +231,11 @@ module Rule = struct
match loc with match loc with
| None -> | None ->
Exn.code_error "rule has targets in different directories" Exn.code_error "rule has targets in different directories"
[ "targets", Sexp.To_sexp.list Path.sexp_of_t [ "targets", Sexp.To_sexp.list Path.to_sexp
(List.map targets ~f:Target.path) (List.map targets ~f:Target.path)
] ]
| Some loc -> | Some loc ->
Loc.fail loc Errors.fail loc
"Rule has targets in different directories.\nTargets:\n%s" "Rule has targets in different directories.\nTargets:\n%s"
(String.concat ~sep:"\n" (String.concat ~sep:"\n"
(List.map targets ~f:(fun t -> (List.map targets ~f:(fun t ->

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
module Target : sig module Target : sig

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Fiber.O open Fiber.O
@ -233,13 +234,13 @@ module Alias0 = struct
if not (Path.is_in_build_dir dir) || String.contains name '/' then if not (Path.is_in_build_dir dir) || String.contains name '/' then
Exn.code_error "Alias0.make: Invalid alias" Exn.code_error "Alias0.make: Invalid alias"
[ "name", Sexp.To_sexp.string name [ "name", Sexp.To_sexp.string name
; "dir", Path.sexp_of_t dir ; "dir", Path.to_sexp dir
]; ];
{ dir; name } { dir; name }
let of_user_written_path ~loc path = let of_user_written_path ~loc path =
if not (Path.is_in_build_dir path) then if not (Path.is_in_build_dir path) then
Loc.fail loc "Invalid alias!\n\ Errors.fail loc "Invalid alias!\n\
Tried to reference path outside build dir: %S" Tried to reference path outside build dir: %S"
(Path.to_string_maybe_quoted path); (Path.to_string_maybe_quoted path);
{ dir = Path.parent_exn path { dir = Path.parent_exn path
@ -304,13 +305,13 @@ module Alias0 = struct
match File_tree.find_dir file_tree src_dir with match File_tree.find_dir file_tree src_dir with
| None -> | None ->
Build.fail { fail = fun () -> Build.fail { fail = fun () ->
Loc.fail loc "Don't know about directory %s!" Errors.fail loc "Don't know about directory %s!"
(Path.to_string_maybe_quoted src_dir) } (Path.to_string_maybe_quoted src_dir) }
| Some dir -> | Some dir ->
dep_rec_internal ~name:t.name ~dir ~ctx_dir dep_rec_internal ~name:t.name ~dir ~ctx_dir
>>^ fun is_empty -> >>^ fun is_empty ->
if is_empty && not (is_standard t.name) then if is_empty && not (is_standard t.name) then
Loc.fail loc Errors.fail loc
"This alias is empty.\n\ "This alias is empty.\n\
Alias %S is not defined in %s or any of its descendants." Alias %S is not defined in %s or any of its descendants."
t.name (Path.to_string_maybe_quoted src_dir) t.name (Path.to_string_maybe_quoted src_dir)
@ -461,7 +462,7 @@ let entry_point t ~f =
| stack -> | stack ->
Exn.code_error Exn.code_error
"Build_system.entry_point: called inside the rule generator callback" "Build_system.entry_point: called inside the rule generator callback"
["stack", Sexp.To_sexp.list Path.sexp_of_t stack] ["stack", Sexp.To_sexp.list Path.to_sexp stack]
); );
f () f ()
@ -564,7 +565,7 @@ let add_spec t fn spec ~copy_source =
| Some (File_spec.T { rule; _ }) -> | Some (File_spec.T { rule; _ }) ->
match copy_source, rule.mode with match copy_source, rule.mode with
| true, (Standard | Not_a_rule_stanza) -> | true, (Standard | Not_a_rule_stanza) ->
Loc.warn (Internal_rule.loc rule ~dir:(Path.parent_exn fn) Errors.warn (Internal_rule.loc rule ~dir:(Path.parent_exn fn)
~file_tree:t.file_tree) ~file_tree:t.file_tree)
"File %s is both generated by a rule and present in the source tree.\n\ "File %s is both generated by a rule and present in the source tree.\n\
As a result, the rule is currently ignored, however this will become an error \ As a result, the rule is currently ignored, however this will become an error \
@ -686,7 +687,7 @@ let remove_old_artifacts t ~dir ~subdirs_to_keep =
let no_rule_found = let no_rule_found =
let fail fn ~loc = let fail fn ~loc =
Loc.fail_opt loc "No rule found for %s" (Utils.describe_target fn) Errors.fail_opt loc "No rule found for %s" (Utils.describe_target fn)
in in
fun t ~loc fn -> fun t ~loc fn ->
match Utils.analyse_target fn with match Utils.analyse_target fn with
@ -1067,7 +1068,7 @@ and load_dir_step2_exn t ~dir ~collector ~lazy_generators =
let present_targets = let present_targets =
Path.Set.diff source_files_for_targtes absent_targets Path.Set.diff source_files_for_targtes absent_targets
in in
Loc.fail Errors.fail
(rule_loc (rule_loc
~file_tree:t.file_tree ~file_tree:t.file_tree
~loc:rule.loc ~loc:rule.loc
@ -1275,13 +1276,13 @@ let update_universe t =
Utils.Cached_digest.remove universe_file; Utils.Cached_digest.remove universe_file;
let n = let n =
if Path.exists universe_file then if Path.exists universe_file then
Sexp.Of_sexp.(parse int) Univ_map.empty Dsexp.Of_sexp.(parse int) Univ_map.empty
(Io.Sexp.load ~mode:Single universe_file) + 1 (Dsexp.Io.load ~mode:Single universe_file) + 1
else else
0 0
in in
make_local_dirs t (Path.Set.singleton Path.build_dir); make_local_dirs t (Path.Set.singleton Path.build_dir);
Io.write_file universe_file (Sexp.to_string ~syntax:Dune (Sexp.To_sexp.int n)) Io.write_file universe_file (Dsexp.to_string ~syntax:Dune (Dsexp.To_sexp.int n))
let do_build t ~request = let do_build t ~request =
entry_point t ~f:(fun () -> entry_point t ~f:(fun () ->
@ -1535,8 +1536,8 @@ let get_collector t ~dir =
"Build_system.get_collector called on external directory" "Build_system.get_collector called on external directory"
else else
"Build_system.get_collector called on closed directory") "Build_system.get_collector called on closed directory")
[ "dir", Path.sexp_of_t dir [ "dir", Path.to_sexp dir
; "load_dir_stack", Sexp.To_sexp.list Path.sexp_of_t t.load_dir_stack ; "load_dir_stack", Sexp.To_sexp.list Path.to_sexp t.load_dir_stack
] ]
let add_rule t (rule : Build_interpret.Rule.t) = let add_rule t (rule : Build_interpret.Rule.t) =
@ -1557,7 +1558,7 @@ let prefix_rules t prefix ~f =
| [] -> () | [] -> ()
| targets -> | targets ->
Exn.code_error "Build_system.prefix_rules' prefix contains targets" Exn.code_error "Build_system.prefix_rules' prefix contains targets"
["targets", Path.Set.sexp_of_t (Build_interpret.Target.paths targets)] ["targets", Path.Set.to_sexp (Build_interpret.Target.paths targets)]
end; end;
let prefix = let prefix =
match t.prefix with match t.prefix with
@ -1620,7 +1621,7 @@ module Alias = struct
let add_action build_system t ~context ~loc ?(locks=[]) ~stamp action = let add_action build_system t ~context ~loc ?(locks=[]) ~stamp action =
let def = get_alias_def build_system t in let def = get_alias_def build_system t in
def.actions <- { stamp = Digest.string (Sexp.to_string ~syntax:Dune stamp) def.actions <- { stamp = Digest.string (Marshal.to_string stamp [])
; action ; action
; locks ; locks
; context ; context

View File

@ -1,5 +1,6 @@
(** Build rules *) (** Build rules *)
open! Stdune
open! Import open! Import
type t type t
@ -173,7 +174,7 @@ module Alias : sig
-> context:Context.t -> context:Context.t
-> loc:Loc.t option -> loc:Loc.t option
-> ?locks:Path.t list -> ?locks:Path.t list
-> stamp:Sexp.t -> stamp:_
-> (unit, Action.t) Build.t -> (unit, Action.t) Build.t
-> unit -> unit
end with type build_system := t end with type build_system := t

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
type styles = Ansi_color.Style.t list type styles = Ansi_color.Style.t list

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
val colorize : key:string -> string -> string val colorize : key:string -> string -> string

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module SC = Super_context module SC = Super_context

View File

@ -1,5 +1,6 @@
(** High-level API for compiling OCaml files *) (** High-level API for compiling OCaml files *)
open! Stdune
open Import open Import
(** Represent a compilation context. (** Represent a compilation context.

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
let local_install_dir = let local_install_dir =
@ -49,7 +50,7 @@ module Display = struct
; "quiet" , Quiet ; "quiet" , Quiet
] ]
let t = enum all let dparse = enum all
end end
module Concurrency = struct module Concurrency = struct
@ -71,7 +72,7 @@ module Concurrency = struct
else else
error error
let t = let dparse =
plain_string (fun ~loc s -> plain_string (fun ~loc s ->
match of_string s with match of_string s with
| Error m -> of_sexp_errorf loc "%s" m | Error m -> of_sexp_errorf loc "%s" m
@ -109,15 +110,15 @@ let default =
; concurrency = if inside_dune then Fixed 1 else Auto ; concurrency = if inside_dune then Fixed 1 else Auto
} }
let t = let dparse =
let%map display = field "display" Display.t ~default:default.display let%map display = field "display" Display.dparse ~default:default.display
and concurrency = field "jobs" Concurrency.t ~default:default.concurrency and concurrency = field "jobs" Concurrency.dparse ~default:default.concurrency
in in
{ display { display
; concurrency ; concurrency
} }
let t = fields t let dparse = fields dparse
let user_config_file = let user_config_file =
Path.relative (Path.of_filename_relative_to_initial_cwd Xdg.config_dir) Path.relative (Path.of_filename_relative_to_initial_cwd Xdg.config_dir)
@ -128,16 +129,16 @@ let () = Lang.register syntax ()
let load_config_file p = let load_config_file p =
match Which_program.t with match Which_program.t with
| Dune -> load p ~f:(fun _lang -> t) | Dune -> load p ~f:(fun _lang -> dparse)
| Jbuilder -> | Jbuilder ->
Io.with_lexbuf_from_file p ~f:(fun lb -> Io.with_lexbuf_from_file p ~f:(fun lb ->
match Dune_lexer.maybe_first_line lb with match Dune_lexer.maybe_first_line lb with
| None -> | None ->
parse (enter t) parse (enter dparse)
(Univ_map.singleton (Syntax.key syntax) (0, 0)) (Univ_map.singleton (Syntax.key syntax) (0, 0))
(Io.Sexp.load p ~mode:Many_as_one ~lexer:Sexp.Lexer.jbuild_token) (Dsexp.Io.load p ~mode:Many_as_one ~lexer:Dsexp.Lexer.jbuild_token)
| Some first_line -> | Some first_line ->
parse_contents lb first_line ~f:(fun _lang -> t)) parse_contents lb first_line ~f:(fun _lang -> dparse))
let load_user_config_file () = let load_user_config_file () =
if Path.exists user_config_file then if Path.exists user_config_file then

View File

@ -32,7 +32,7 @@ module Display : sig
| Verbose (** Display all commands fully *) | Verbose (** Display all commands fully *)
| Quiet (** Only display errors *) | Quiet (** Only display errors *)
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
val all : (string * t) list val all : (string * t) list
end end
@ -58,7 +58,7 @@ include S with type 'a field = 'a
module Partial : S with type 'a field := 'a option module Partial : S with type 'a field := 'a option
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
val merge : t -> Partial.t -> t val merge : t -> Partial.t -> t

View File

@ -3,6 +3,6 @@
(library (library
(name configurator) (name configurator)
(public_name dune.configurator) (public_name dune.configurator)
(libraries stdune ocaml_config) (libraries stdune ocaml_config dsexp)
(flags (:standard -safe-string (:include flags/flags.sexp))) (flags (:standard -safe-string (:include flags/flags.sexp)))
(preprocess no_preprocessing)) (preprocess no_preprocessing))

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
let sprintf = Printf.sprintf let sprintf = Printf.sprintf
let eprintf = Printf.eprintf let eprintf = Printf.eprintf
@ -75,8 +75,8 @@ module Flags = struct
let write_sexp fname s = let write_sexp fname s =
let path = Path.in_source fname in let path = Path.in_source fname in
let sexp = Usexp.List (List.map s ~f:(fun s -> Usexp.Quoted_string s)) in let sexp = Dsexp.List (List.map s ~f:(fun s -> Dsexp.Quoted_string s)) in
Io.write_file path (Usexp.to_string sexp ~syntax:Dune) Io.write_file path (Dsexp.to_string sexp ~syntax:Dune)
end end
module Find_in_path = struct module Find_in_path = struct

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Fiber.O open Fiber.O
@ -10,8 +11,8 @@ module Kind = struct
end end
type t = Default | Opam of Opam.t type t = Default | Opam of Opam.t
let sexp_of_t : t -> Sexp.t = function let to_sexp : t -> Sexp.t = function
| Default -> Sexp.unsafe_atom_of_string "default" | Default -> Sexp.To_sexp.string "default"
| Opam o -> | Opam o ->
Sexp.To_sexp.(record [ "root" , string o.root Sexp.To_sexp.(record [ "root" , string o.root
; "switch", string o.switch ; "switch", string o.switch
@ -85,12 +86,12 @@ type t =
; which_cache : (string, Path.t option) Hashtbl.t ; which_cache : (string, Path.t option) Hashtbl.t
} }
let sexp_of_t t = let to_sexp t =
let open Sexp.To_sexp in let open Sexp.To_sexp in
let path = Path.sexp_of_t in let path = Path.to_sexp in
record record
[ "name", string t.name [ "name", string t.name
; "kind", Kind.sexp_of_t t.kind ; "kind", Kind.to_sexp t.kind
; "profile", string t.profile ; "profile", string t.profile
; "merlin", bool t.merlin ; "merlin", bool t.merlin
; "for_host", option string (Option.map t.for_host ~f:(fun t -> t.name)) ; "for_host", option string (Option.map t.for_host ~f:(fun t -> t.name))
@ -102,16 +103,16 @@ let sexp_of_t t =
; "ocamlopt", option path t.ocamlopt ; "ocamlopt", option path t.ocamlopt
; "ocamldep", path t.ocamldep ; "ocamldep", path t.ocamldep
; "ocamlmklib", path t.ocamlmklib ; "ocamlmklib", path t.ocamlmklib
; "env", Env.sexp_of_t (Env.diff t.env Env.initial) ; "env", Env.to_sexp (Env.diff t.env Env.initial)
; "findlib_path", list path (Findlib.path t.findlib) ; "findlib_path", list path (Findlib.path t.findlib)
; "arch_sixtyfour", bool t.arch_sixtyfour ; "arch_sixtyfour", bool t.arch_sixtyfour
; "natdynlink_supported", ; "natdynlink_supported",
bool (Dynlink_supported.By_the_os.get t.natdynlink_supported) bool (Dynlink_supported.By_the_os.get t.natdynlink_supported)
; "supports_shared_libraries", ; "supports_shared_libraries",
bool (Dynlink_supported.By_the_os.get t.supports_shared_libraries) bool (Dynlink_supported.By_the_os.get t.supports_shared_libraries)
; "opam_vars", string_hashtbl string t.opam_var_cache ; "opam_vars", Hashtbl.to_sexp string string t.opam_var_cache
; "ocaml_config", Ocaml_config.sexp_of_t t.ocaml_config ; "ocaml_config", Ocaml_config.to_sexp t.ocaml_config
; "which", string_hashtbl (option path) t.which_cache ; "which", Hashtbl.to_sexp string (option path) t.which_cache
] ]
let compare a b = compare a.name b.name let compare a b = compare a.name b.name
@ -269,7 +270,7 @@ let create ~(kind : Kind.t) ~path ~env ~env_nodes ~name ~merlin ~targets
%s" %s"
(Path.to_string ocamlc) msg (Path.to_string ocamlc) msg
| Error (Makefile_config file, msg) -> | Error (Makefile_config file, msg) ->
Loc.fail (Loc.in_file (Path.to_string file)) "%s" msg Errors.fail (Loc.in_file (Path.to_string file)) "%s" msg
in in
Fiber.fork_and_join Fiber.fork_and_join
findlib_path findlib_path
@ -451,8 +452,8 @@ let create_for_opam ?root ~env ~env_nodes ~targets ~profile ~switch ~name
["config"; "env"; "--root"; root; "--switch"; switch; "--sexp"] ["config"; "env"; "--root"; root; "--switch"; switch; "--sexp"]
>>= fun s -> >>= fun s ->
let vars = let vars =
Usexp.parse_string ~fname:"<opam output>" ~mode:Single s Dsexp.parse_string ~fname:"<opam output>" ~mode:Single s
|> Sexp.Of_sexp.(parse (list (pair string string)) Univ_map.empty) |> Dsexp.Of_sexp.(parse (list (pair string string)) Univ_map.empty)
|> Env.Map.of_list_multi |> Env.Map.of_list_multi
|> Env.Map.mapi ~f:(fun var values -> |> Env.Map.mapi ~f:(fun var values ->
match List.rev values with match List.rev values with

View File

@ -18,6 +18,7 @@
it is obtained by looking in another context. it is obtained by looking in another context.
*) *)
open! Stdune
open! Import open! Import
module Kind : sig module Kind : sig
@ -127,7 +128,7 @@ type t =
; which_cache : (string, Path.t option) Hashtbl.t ; which_cache : (string, Path.t option) Hashtbl.t
} }
val sexp_of_t : t -> Sexp.t val to_sexp : t -> Sexp.t
(** Compare the context names *) (** Compare the context names *)
val compare : t -> t -> Ordering.t val compare : t -> t -> Ordering.t

View File

@ -1,4 +1,4 @@
open Import open! Stdune
module Entry = struct module Entry = struct
type t = type t =
@ -14,8 +14,8 @@ module Entry = struct
| Library (path, lib_name) -> | Library (path, lib_name) ->
sprintf "library %S in %s" lib_name (Path.to_string_maybe_quoted path) sprintf "library %S in %s" lib_name (Path.to_string_maybe_quoted path)
| Preprocess l -> | Preprocess l ->
Sexp.to_string ~syntax:Dune Sexp.to_string
(List [ Sexp.unsafe_atom_of_string "pps" (List [ Atom "pps"
; Sexp.To_sexp.(list string) l]) ; Sexp.To_sexp.(list string) l])
| Loc loc -> | Loc loc ->
Loc.to_file_colon_line loc Loc.to_file_colon_line loc

View File

@ -1,6 +1,6 @@
(** Dependency path *) (** Dependency path *)
open Stdune open! Stdune
module Entry : sig module Entry : sig
type t = type t =

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module Menhir_rules = Menhir module Menhir_rules = Menhir
open Dune_file open Dune_file
@ -39,7 +40,7 @@ end = struct
match m with match m with
| Ok m -> Some m | Ok m -> Some m
| Error s -> | Error s ->
Loc.fail loc "Module %a doesn't exist." Module.Name.pp s) Errors.fail loc "Module %a doesn't exist." Module.Name.pp s)
, modules , modules
) )
@ -100,28 +101,28 @@ end = struct
if missing_intf_only <> [] then begin if missing_intf_only <> [] then begin
match Ordered_set_lang.loc buildable.modules_without_implementation with match Ordered_set_lang.loc buildable.modules_without_implementation with
| None -> | None ->
Loc.warn buildable.loc Errors.warn buildable.loc
"Some modules don't have an implementation.\ "Some modules don't have an implementation.\
\nYou need to add the following field to this stanza:\ \nYou need to add the following field to this stanza:\
\n\ \n\
\n %s\ \n %s\
\n\ \n\
\nThis will become an error in the future." \nThis will become an error in the future."
(let tag = Sexp.unsafe_atom_of_string (let tag = Dsexp.unsafe_atom_of_string
"modules_without_implementation" in "modules_without_implementation" in
let modules = let modules =
missing_intf_only missing_intf_only
|> uncapitalized |> uncapitalized
|> List.map ~f:Sexp.To_sexp.string |> List.map ~f:Dsexp.To_sexp.string
in in
Sexp.to_string ~syntax:Dune (List (tag :: modules))) Dsexp.to_string ~syntax:Dune (List (tag :: modules)))
| Some loc -> | Some loc ->
let list_modules l = let list_modules l =
uncapitalized l uncapitalized l
|> List.map ~f:(sprintf "- %s") |> List.map ~f:(sprintf "- %s")
|> String.concat ~sep:"\n" |> String.concat ~sep:"\n"
in in
Loc.warn loc Errors.warn loc
"The following modules must be listed here as they don't \ "The following modules must be listed here as they don't \
have an implementation:\n\ have an implementation:\n\
%s\n\ %s\n\
@ -135,7 +136,7 @@ end = struct
|> Option.value_exn |> Option.value_exn
in in
(* CR-soon jdimino for jdimino: report all errors *) (* CR-soon jdimino for jdimino: report all errors *)
Loc.fail loc Errors.fail loc
"Module %a has an implementation, it cannot be listed here" "Module %a has an implementation, it cannot be listed here"
Module.Name.pp module_name Module.Name.pp module_name
end end
@ -154,7 +155,7 @@ end = struct
) )
in in
Module.Name.Map.iteri fake_modules ~f:(fun m loc -> Module.Name.Map.iteri fake_modules ~f:(fun m loc ->
Loc.warn loc "Module %a is excluded but it doesn't exist." Errors.warn loc "Module %a is excluded but it doesn't exist."
Module.Name.pp m Module.Name.pp m
); );
check_invalid_module_listing ~buildable:conf ~intf_only ~modules check_invalid_module_listing ~buildable:conf ~intf_only ~modules
@ -280,8 +281,8 @@ let mlds t (doc : Documentation.t) =
| Some x -> x | Some x -> x
| None -> | None ->
Exn.code_error "Dir_contents.mlds" Exn.code_error "Dir_contents.mlds"
[ "doc", Loc.sexp_of_t doc.loc [ "doc", Loc.to_sexp doc.loc
; "available", Sexp.To_sexp.(list Loc.sexp_of_t) ; "available", Sexp.To_sexp.(list Loc.to_sexp)
(List.map map ~f:(fun (d, _) -> d.Documentation.loc)) (List.map map ~f:(fun (d, _) -> d.Documentation.loc))
] ]
@ -378,7 +379,7 @@ let build_modules_map (d : Super_context.Dir_with_jbuild.t) ~modules =
with with
| Ok x -> x | Ok x -> x
| Error (name, _, (lib2, _)) -> | Error (name, _, (lib2, _)) ->
Loc.fail lib2.buildable.loc Errors.fail lib2.buildable.loc
"Library %S appears for the second time \ "Library %S appears for the second time \
in this directory" in this directory"
name name
@ -390,7 +391,7 @@ let build_modules_map (d : Super_context.Dir_with_jbuild.t) ~modules =
with with
| Ok x -> x | Ok x -> x
| Error (name, _, (exes2, _)) -> | Error (name, _, (exes2, _)) ->
Loc.fail exes2.buildable.loc Errors.fail exes2.buildable.loc
"Executable %S appears for the second time \ "Executable %S appears for the second time \
in this directory" in this directory"
name name
@ -416,7 +417,7 @@ let build_modules_map (d : Super_context.Dir_with_jbuild.t) ~modules =
Option.some_if (n = name) b.loc) Option.some_if (n = name) b.loc)
|> List.sort ~compare |> List.sort ~compare
in in
Loc.fail (Loc.in_file (List.hd locs).start.pos_fname) Errors.fail (Loc.in_file (List.hd locs).start.pos_fname)
"Module %a is used in several stanzas:@\n\ "Module %a is used in several stanzas:@\n\
@[<v>%a@]@\n\ @[<v>%a@]@\n\
@[%a@]" @[%a@]"
@ -441,7 +442,7 @@ let build_modules_map (d : Super_context.Dir_with_jbuild.t) ~modules =
List.sort ~compare List.sort ~compare
(b.Buildable.loc :: List.map rest ~f:(fun b -> b.Buildable.loc)) (b.Buildable.loc :: List.map rest ~f:(fun b -> b.Buildable.loc))
in in
Loc.warn (Loc.in_file b.loc.start.pos_fname) Errors.warn (Loc.in_file b.loc.start.pos_fname)
"Module %a is used in several stanzas:@\n\ "Module %a is used in several stanzas:@\n\
@[<v>%a@]@\n\ @[<v>%a@]@\n\
@[%a@]@\n\ @[%a@]@\n\
@ -477,7 +478,7 @@ let build_mlds_map (d : Super_context.Dir_with_jbuild.t) ~files =
| Some s -> | Some s ->
s s
| None -> | None ->
Loc.fail loc "%s.mld doesn't exist in %s" s Errors.fail loc "%s.mld doesn't exist in %s" s
(Path.to_string_maybe_quoted (Path.to_string_maybe_quoted
(Path.drop_optional_build_context dir)) (Path.drop_optional_build_context dir))
) )
@ -513,7 +514,7 @@ module Dir_status = struct
match stanza with match stanza with
| Include_subdirs (loc, x) -> | Include_subdirs (loc, x) ->
if Option.is_some acc then if Option.is_some acc then
Loc.fail loc "The 'include_subdirs' stanza cannot appear \ Errors.fail loc "The 'include_subdirs' stanza cannot appear \
more than once"; more than once";
Some x Some x
| _ -> acc) | _ -> acc)
@ -523,7 +524,7 @@ module Dir_status = struct
match stanza with match stanza with
| Library { buildable; _} | Executables { buildable; _ } | Library { buildable; _} | Executables { buildable; _ }
| Tests { exes = { buildable; _ }; _ } -> | Tests { exes = { buildable; _ }; _ } ->
Loc.fail buildable.loc Errors.fail buildable.loc
"This stanza is not allowed in a sub-directory of directory with \ "This stanza is not allowed in a sub-directory of directory with \
(include_subdirs unqualified).\n\ (include_subdirs unqualified).\n\
Hint: add (include_subdirs no) to this file." Hint: add (include_subdirs no) to this file."
@ -663,7 +664,7 @@ let rec get sctx ~dir =
~f:(fun acc (dir, files) -> ~f:(fun acc (dir, files) ->
let modules = modules_of_files ~dir ~files in let modules = modules_of_files ~dir ~files in
Module.Name.Map.union acc modules ~f:(fun name x y -> Module.Name.Map.union acc modules ~f:(fun name x y ->
Loc.fail (Loc.in_file Errors.fail (Loc.in_file
(Path.to_string (Path.to_string
(match File_tree.Dir.dune_file ft_dir with (match File_tree.Dir.dune_file ft_dir with
| None -> | None ->

View File

@ -4,6 +4,7 @@
in the source tree or generated by user rules to library, in the source tree or generated by user rules to library,
executables, tests and documentation stanzas. *) executables, tests and documentation stanzas. *)
open! Stdune
open Import open Import
type t type t

869
src/dsexp/dsexp.ml Normal file
View File

@ -0,0 +1,869 @@
open! Stdune
module Atom = Atom
module Template = Template
type syntax = Atom.syntax = Jbuild | Dune
type t =
| Atom of Atom.t
| Quoted_string of string
| List of t list
| Template of Template.t
let atom_or_quoted_string s =
if Atom.is_valid_dune s then
Atom (Atom.of_string s)
else
Quoted_string s
let atom s = Atom (Atom.of_string s)
let unsafe_atom_of_string s = atom s
let rec to_string t ~syntax =
match t with
| Atom a -> Atom.print a syntax
| Quoted_string s -> Escape.quoted s ~syntax
| List l ->
Printf.sprintf "(%s)" (List.map l ~f:(to_string ~syntax)
|> String.concat ~sep:" ")
| Template t -> Template.to_string t ~syntax
let rec pp syntax ppf = function
| Atom s ->
Format.pp_print_string ppf (Atom.print s syntax)
| Quoted_string s ->
Format.pp_print_string ppf (Escape.quoted ~syntax s)
| List [] ->
Format.pp_print_string ppf "()"
| List (first :: rest) ->
Format.pp_open_box ppf 1;
Format.pp_print_string ppf "(";
Format.pp_open_hvbox ppf 0;
pp syntax ppf first;
List.iter rest ~f:(fun sexp ->
Format.pp_print_space ppf ();
pp syntax ppf sexp);
Format.pp_close_box ppf ();
Format.pp_print_string ppf ")";
Format.pp_close_box ppf ()
| Template t -> Template.pp syntax ppf t
let pp_quoted =
let rec loop = function
| Atom (A s) as t ->
if Atom.is_valid_dune s then
t
else
Quoted_string s
| List xs -> List (List.map ~f:loop xs)
| (Quoted_string _ | Template _) as t -> t
in
fun ppf t -> pp Dune ppf (loop t)
let pp_print_quoted_string ppf s =
let syntax = Dune in
if String.contains s '\n' then begin
match String.split s ~on:'\n' with
| [] -> Format.pp_print_string ppf (Escape.quoted ~syntax s)
| first :: rest ->
Format.fprintf ppf "@[<hv 1>\"@{<atom>%s"
(Escape.escaped ~syntax first);
List.iter rest ~f:(fun s ->
Format.fprintf ppf "@,\\n%s" (Escape.escaped ~syntax s));
Format.fprintf ppf "@}\"@]"
end else
Format.pp_print_string ppf (Escape.quoted ~syntax s)
let rec pp_split_strings ppf = function
| Atom s -> Format.pp_print_string ppf (Atom.print s Atom.Dune)
| Quoted_string s -> pp_print_quoted_string ppf s
| List [] ->
Format.pp_print_string ppf "()"
| List (first :: rest) ->
Format.pp_open_box ppf 1;
Format.pp_print_string ppf "(";
Format.pp_open_hvbox ppf 0;
pp_split_strings ppf first;
List.iter rest ~f:(fun sexp ->
Format.pp_print_space ppf ();
pp_split_strings ppf sexp);
Format.pp_close_box ppf ();
Format.pp_print_string ppf ")";
Format.pp_close_box ppf ()
| Template t -> Template.pp_split_strings ppf t
type formatter_state =
| In_atom
| In_makefile_action
| In_makefile_stuff
let prepare_formatter ppf =
let state = ref [] in
Format.pp_set_mark_tags ppf true;
let ofuncs = Format.pp_get_formatter_out_functions ppf () in
let tfuncs = Format.pp_get_formatter_tag_functions ppf () in
Format.pp_set_formatter_tag_functions ppf
{ tfuncs with
mark_open_tag = (function
| "atom" -> state := In_atom :: !state; ""
| "makefile-action" -> state := In_makefile_action :: !state; ""
| "makefile-stuff" -> state := In_makefile_stuff :: !state; ""
| s -> tfuncs.mark_open_tag s)
; mark_close_tag = (function
| "atom" | "makefile-action" | "makefile-stuff" -> state := List.tl !state; ""
| s -> tfuncs.mark_close_tag s)
};
Format.pp_set_formatter_out_functions ppf
{ ofuncs with
out_newline = (fun () ->
match !state with
| [In_atom; In_makefile_action] ->
ofuncs.out_string "\\\n\t" 0 3
| [In_atom] ->
ofuncs.out_string "\\\n" 0 2
| [In_makefile_action] ->
ofuncs.out_string " \\\n\t" 0 4
| [In_makefile_stuff] ->
ofuncs.out_string " \\\n" 0 3
| [] ->
ofuncs.out_string "\n" 0 1
| _ -> assert false)
; out_spaces = (fun n ->
ofuncs.out_spaces
(match !state with
| In_atom :: _ -> max 0 (n - 2)
| _ -> n))
}
module Ast = struct
type dsexp = t
type t =
| Atom of Loc.t * Atom.t
| Quoted_string of Loc.t * string
| Template of Template.t
| List of Loc.t * t list
let atom_or_quoted_string loc s =
match atom_or_quoted_string s with
| Atom a -> Atom (loc, a)
| Quoted_string s -> Quoted_string (loc, s)
| Template _
| List _ -> assert false
let loc (Atom (loc, _) | Quoted_string (loc, _) | List (loc, _)
| Template { loc ; _ }) = loc
let rec remove_locs t : dsexp =
match t with
| Template t -> Template (Template.remove_locs t)
| Atom (_, s) -> Atom s
| Quoted_string (_, s) -> Quoted_string s
| List (_, l) -> List (List.map l ~f:remove_locs)
end
let rec add_loc t ~loc : Ast.t =
match t with
| Atom s -> Atom (loc, s)
| Quoted_string s -> Quoted_string (loc, s)
| List l -> List (loc, List.map l ~f:(add_loc ~loc))
| Template t -> Template { t with loc }
module Parse_error = struct
include Lexer.Error
let loc t : Loc.t = { start = t.start; stop = t.stop }
let message t = t.message
end
exception Parse_error = Lexer.Error
module Lexer = Lexer
module Parser = struct
let error (loc : Loc.t) message =
raise (Parse_error
{ start = loc.start
; stop = loc.stop
; message
})
module Mode = struct
type 'a t =
| Single : Ast.t t
| Many : Ast.t list t
| Many_as_one : Ast.t t
let make_result : type a. a t -> Lexing.lexbuf -> Ast.t list -> a
= fun t lexbuf sexps ->
match t with
| Single -> begin
match sexps with
| [sexp] -> sexp
| [] -> error (Loc.of_lexbuf lexbuf) "no s-expression found in input"
| _ :: sexp :: _ ->
error (Ast.loc sexp) "too many s-expressions found in input"
end
| Many -> sexps
| Many_as_one ->
match sexps with
| [] -> List (Loc.in_file lexbuf.lex_curr_p.pos_fname, [])
| x :: l ->
let last = List.fold_left l ~init:x ~f:(fun _ x -> x) in
let loc = { (Ast.loc x) with stop = (Ast.loc last).stop } in
List (loc, x :: l)
end
let rec loop depth lexer lexbuf acc =
match (lexer lexbuf : Lexer.Token.t) with
| Atom a ->
let loc = Loc.of_lexbuf lexbuf in
loop depth lexer lexbuf (Ast.Atom (loc, a) :: acc)
| Quoted_string s ->
let loc = Loc.of_lexbuf lexbuf in
loop depth lexer lexbuf (Quoted_string (loc, s) :: acc)
| Template t ->
let loc = Loc.of_lexbuf lexbuf in
loop depth lexer lexbuf (Template { t with loc } :: acc)
| Lparen ->
let start = Lexing.lexeme_start_p lexbuf in
let sexps = loop (depth + 1) lexer lexbuf [] in
let stop = Lexing.lexeme_end_p lexbuf in
loop depth lexer lexbuf (List ({ start; stop }, sexps) :: acc)
| Rparen ->
if depth = 0 then
error (Loc.of_lexbuf lexbuf)
"right parenthesis without matching left parenthesis";
List.rev acc
| Sexp_comment ->
let sexps =
let loc = Loc.of_lexbuf lexbuf in
match loop depth lexer lexbuf [] with
| _ :: sexps -> sexps
| [] -> error loc "s-expression missing after #;"
in
List.rev_append acc sexps
| Eof ->
if depth > 0 then
error (Loc.of_lexbuf lexbuf)
"unclosed parenthesis at end of input";
List.rev acc
let parse ~mode ?(lexer=Lexer.token) lexbuf =
loop 0 lexer lexbuf []
|> Mode.make_result mode lexbuf
end
let parse_string ~fname ~mode ?lexer str =
let lb = Lexing.from_string str in
lb.lex_curr_p <-
{ pos_fname = fname
; pos_lnum = 1
; pos_bol = 0
; pos_cnum = 0
};
Parser.parse ~mode ?lexer lb
type dsexp = t
module To_sexp = struct
type nonrec 'a t = 'a -> t
let unit () = List []
let string = atom_or_quoted_string
let int n = Atom (Atom.of_int n)
let float f = Atom (Atom.of_float f)
let bool b = Atom (Atom.of_bool b)
let pair fa fb (a, b) = List [fa a; fb b]
let triple fa fb fc (a, b, c) = List [fa a; fb b; fc c]
let list f l = List (List.map l ~f)
let array f a = list f (Array.to_list a)
let option f = function
| None -> List []
| Some x -> List [f x]
let record l =
List (List.map l ~f:(fun (n, v) -> List [Atom(Atom.of_string n); v]))
type field = string * dsexp option
let field name f ?(equal=(=)) ?default v =
match default with
| None -> (name, Some (f v))
| Some d ->
if equal d v then
(name, None)
else
(name, Some (f v))
let field_o name f v = (name, Option.map ~f v)
let record_fields (l : field list) =
List (List.filter_map l ~f:(fun (k, v) ->
Option.map v ~f:(fun v -> List[Atom (Atom.of_string k); v])))
let unknown _ = unsafe_atom_of_string "<unknown>"
end
module Of_sexp = struct
type ast = Ast.t =
| Atom of Loc.t * Atom.t
| Quoted_string of Loc.t * string
| Template of Template.t
| List of Loc.t * ast list
type hint =
{ on: string
; candidates: string list
}
exception Of_sexp of Loc.t * string * hint option
let of_sexp_error ?hint loc msg =
raise (Of_sexp (loc, msg, hint))
let of_sexp_errorf ?hint loc fmt =
Printf.ksprintf (fun msg -> of_sexp_error loc ?hint msg) fmt
let no_templates ?hint loc fmt =
Printf.ksprintf (fun msg ->
of_sexp_error loc ?hint ("No variables allowed " ^ msg)) fmt
type unparsed_field =
{ values : Ast.t list
; entry : Ast.t
; prev : unparsed_field option (* Previous occurrence of this field *)
}
module Name = struct
type t = string
let compare a b =
let alen = String.length a and blen = String.length b in
match Int.compare alen blen with
| Eq -> String.compare a b
| ne -> ne
end
module Name_map = Map.Make(Name)
type values = Ast.t list
type fields =
{ unparsed : unparsed_field Name_map.t
; known : string list
}
(* Arguments are:
- the location of the whole list
- the first atom when parsing a constructor or a field
- the universal map holding the user context
*)
type 'kind context =
| Values : Loc.t * string option * Univ_map.t -> values context
| Fields : Loc.t * string option * Univ_map.t -> fields context
type ('a, 'kind) parser = 'kind context -> 'kind -> 'a * 'kind
type 'a t = ('a, values) parser
type 'a fields_parser = ('a, fields) parser
let return x _ctx state = (x, state)
let (>>=) t f ctx state =
let x, state = t ctx state in
f x ctx state
let (>>|) t f ctx state =
let x, state = t ctx state in
(f x, state)
let (>>>) a b ctx state =
let (), state = a ctx state in
b ctx state
let map t ~f = t >>| f
let try_ t f ctx state =
try
t ctx state
with exn ->
f exn ctx state
let get_user_context : type k. k context -> Univ_map.t = function
| Values (_, _, uc) -> uc
| Fields (_, _, uc) -> uc
let get key ctx state = (Univ_map.find (get_user_context ctx) key, state)
let get_all ctx state = (get_user_context ctx, state)
let set : type a b k. a Univ_map.Key.t -> a -> (b, k) parser -> (b, k) parser
= fun key v t ctx state ->
match ctx with
| Values (loc, cstr, uc) ->
t (Values (loc, cstr, Univ_map.add uc key v)) state
| Fields (loc, cstr, uc) ->
t (Fields (loc, cstr, Univ_map.add uc key v)) state
let set_many : type a k. Univ_map.t -> (a, k) parser -> (a, k) parser
= fun map t ctx state ->
match ctx with
| Values (loc, cstr, uc) ->
t (Values (loc, cstr, Univ_map.superpose uc map)) state
| Fields (loc, cstr, uc) ->
t (Fields (loc, cstr, Univ_map.superpose uc map)) state
let loc : type k. k context -> k -> Loc.t * k = fun ctx state ->
match ctx with
| Values (loc, _, _) -> (loc, state)
| Fields (loc, _, _) -> (loc, state)
let at_eos : type k. k context -> k -> bool = fun ctx state ->
match ctx with
| Values _ -> state = []
| Fields _ -> Name_map.is_empty state.unparsed
let eos ctx state = (at_eos ctx state, state)
let if_eos ~then_ ~else_ ctx state =
if at_eos ctx state then
then_ ctx state
else
else_ ctx state
let repeat : 'a t -> 'a list t =
let rec loop t acc ctx l =
match l with
| [] -> (List.rev acc, [])
| _ ->
let x, l = t ctx l in
loop t (x :: acc) ctx l
in
fun t ctx state -> loop t [] ctx state
let result : type a k. k context -> a * k -> a =
fun ctx (v, state) ->
match ctx with
| Values (_, cstr, _) -> begin
match state with
| [] -> v
| sexp :: _ ->
match cstr with
| None ->
of_sexp_errorf (Ast.loc sexp) "This value is unused"
| Some s ->
of_sexp_errorf (Ast.loc sexp) "Too many argument for %s" s
end
| Fields _ -> begin
match Name_map.choose state.unparsed with
| None -> v
| Some (name, { entry; _ }) ->
let name_loc =
match entry with
| List (_, s :: _) -> Ast.loc s
| _ -> assert false
in
of_sexp_errorf ~hint:{ on = name; candidates = state.known }
name_loc "Unknown field %s" name
end
let parse t context sexp =
let ctx = Values (Ast.loc sexp, None, context) in
result ctx (t ctx [sexp])
let capture ctx state =
let f t =
result ctx (t ctx state)
in
(f, [])
let end_of_list (Values (loc, cstr, _)) =
match cstr with
| None ->
let loc = { loc with start = loc.stop } in
of_sexp_errorf loc "Premature end of list"
| Some s ->
of_sexp_errorf loc "Not enough arguments for %s" s
[@@inline never]
let next f ctx sexps =
match sexps with
| [] -> end_of_list ctx
| sexp :: sexps -> (f sexp, sexps)
[@@inline always]
let next_with_user_context f ctx sexps =
match sexps with
| [] -> end_of_list ctx
| sexp :: sexps -> (f (get_user_context ctx) sexp, sexps)
[@@inline always]
let peek _ctx sexps =
match sexps with
| [] -> (None, sexps)
| sexp :: _ -> (Some sexp, sexps)
[@@inline always]
let peek_exn ctx sexps =
match sexps with
| [] -> end_of_list ctx
| sexp :: _ -> (sexp, sexps)
[@@inline always]
let junk = next ignore
let junk_everything : type k. (unit, k) parser = fun ctx state ->
match ctx with
| Values _ -> ((), [])
| Fields _ -> ((), { state with unparsed = Name_map.empty })
let keyword kwd =
next (function
| Atom (_, s) when Atom.to_string s = kwd -> ()
| sexp -> of_sexp_errorf (Ast.loc sexp) "'%s' expected" kwd)
let match_keyword l ~fallback =
peek >>= function
| Some (Atom (_, A s)) -> begin
match List.assoc l s with
| Some t -> junk >>> t
| None -> fallback
end
| _ -> fallback
let until_keyword kwd ~before ~after =
let rec loop acc =
peek >>= function
| None -> return (List.rev acc, None)
| Some (Atom (_, A s)) when s = kwd ->
junk >>> after >>= fun x ->
return (List.rev acc, Some x)
| _ ->
before >>= fun x ->
loop (x :: acc)
in
loop []
let plain_string f =
next (function
| Atom (loc, A s) | Quoted_string (loc, s) -> f ~loc s
| Template { loc ; _ } | List (loc, _) ->
of_sexp_error loc "Atom or quoted string expected")
let enter t =
next_with_user_context (fun uc sexp ->
match sexp with
| List (loc, l) ->
let ctx = Values (loc, None, uc) in
result ctx (t ctx l)
| sexp ->
of_sexp_error (Ast.loc sexp) "List expected")
let if_list ~then_ ~else_ =
peek_exn >>= function
| List _ -> then_
| _ -> else_
let if_paren_colon_form ~then_ ~else_ =
peek_exn >>= function
| List (_, Atom (loc, A s) :: _) when String.is_prefix s ~prefix:":" ->
let name = String.sub s ~pos:1 ~len:(String.length s - 1) in
enter
(junk >>= fun () ->
then_ >>| fun f ->
f (loc, name))
| _ ->
else_
let fix f =
let rec p = lazy (f r)
and r ast = (Lazy.force p) ast in
r
let loc_between_states : type k. k context -> k -> k -> Loc.t
= fun ctx state1 state2 ->
match ctx with
| Values _ -> begin
match state1 with
| sexp :: rest when rest == state2 -> (* common case *)
Ast.loc sexp
| [] ->
let (Values (loc, _, _)) = ctx in
{ loc with start = loc.stop }
| sexp :: rest ->
let loc = Ast.loc sexp in
let rec search last l =
if l == state2 then
{ loc with stop = (Ast.loc last).stop }
else
match l with
| [] ->
let (Values (loc, _, _)) = ctx in
{ (Ast.loc sexp) with stop = loc.stop }
| sexp :: rest ->
search sexp rest
in
search sexp rest
end
| Fields _ ->
let parsed =
Name_map.merge state1.unparsed state2.unparsed
~f:(fun _key before after ->
match before, after with
| Some _, None -> before
| _ -> None)
in
match
Name_map.values parsed
|> List.map ~f:(fun f -> Ast.loc f.entry)
|> List.sort ~compare:(fun a b ->
Int.compare a.Loc.start.pos_cnum b.start.pos_cnum)
with
| [] ->
let (Fields (loc, _, _)) = ctx in
loc
| first :: l ->
let last = List.fold_left l ~init:first ~f:(fun _ x -> x) in
{ first with stop = last.stop }
let located t ctx state1 =
let x, state2 = t ctx state1 in
((loc_between_states ctx state1 state2, x), state2)
let raw = next (fun x -> x)
let unit =
next
(function
| List (_, []) -> ()
| sexp -> of_sexp_error (Ast.loc sexp) "() expected")
let basic desc f =
next (function
| Template { loc; _ } | List (loc, _) | Quoted_string (loc, _) ->
of_sexp_errorf loc "%s expected" desc
| Atom (loc, s) ->
match f (Atom.to_string s) with
| Result.Error () ->
of_sexp_errorf loc "%s expected" desc
| Ok x -> x)
let string = plain_string (fun ~loc:_ x -> x)
let int =
basic "Integer" (fun s ->
match int_of_string s with
| x -> Ok x
| exception _ -> Result.Error ())
let float =
basic "Float" (fun s ->
match float_of_string s with
| x -> Ok x
| exception _ -> Result.Error ())
let pair a b =
enter
(a >>= fun a ->
b >>= fun b ->
return (a, b))
let triple a b c =
enter
(a >>= fun a ->
b >>= fun b ->
c >>= fun c ->
return (a, b, c))
let list t = enter (repeat t)
let array t = list t >>| Array.of_list
let option t =
enter
(eos >>= function
| true -> return None
| false -> t >>| Option.some)
let find_cstr cstrs loc name ctx values =
match List.assoc cstrs name with
| Some t ->
result ctx (t ctx values)
| None ->
of_sexp_errorf loc
~hint:{ on = name
; candidates = List.map cstrs ~f:fst
}
"Unknown constructor %s" name
let sum cstrs =
next_with_user_context (fun uc sexp ->
match sexp with
| Atom (loc, A s) ->
find_cstr cstrs loc s (Values (loc, Some s, uc)) []
| Template { loc; _ }
| Quoted_string (loc, _) ->
of_sexp_error loc "Atom expected"
| List (loc, []) ->
of_sexp_error loc "Non-empty list expected"
| List (loc, name :: args) ->
match name with
| Quoted_string (loc, _) | List (loc, _) | Template { loc; _ } ->
of_sexp_error loc "Atom expected"
| Atom (s_loc, A s) ->
find_cstr cstrs s_loc s (Values (loc, Some s, uc)) args)
let enum cstrs =
next (function
| Quoted_string (loc, _)
| Template { loc; _ }
| List (loc, _) -> of_sexp_error loc "Atom expected"
| Atom (loc, A s) ->
match List.assoc cstrs s with
| Some value -> value
| None ->
of_sexp_errorf loc
~hint:{ on = s
; candidates = List.map cstrs ~f:fst
}
"Unknown value %s" s)
let bool = enum [ ("true", true); ("false", false) ]
let consume name state =
{ unparsed = Name_map.remove state.unparsed name
; known = name :: state.known
}
let add_known name state =
{ state with known = name :: state.known }
let map_validate t ~f ctx state1 =
let x, state2 = t ctx state1 in
match f x with
| Result.Ok x -> (x, state2)
| Error msg ->
let loc = loc_between_states ctx state1 state2 in
of_sexp_errorf loc "%s" msg
let field_missing loc name =
of_sexp_errorf loc "field %s missing" name
[@@inline never]
let field_present_too_many_times _ name entries =
match entries with
| _ :: second :: _ ->
of_sexp_errorf (Ast.loc second) "Field %S is present too many times"
name
| _ -> assert false
let multiple_occurrences ?(on_dup=field_present_too_many_times) uc name last =
let rec collect acc x =
let acc = x.entry :: acc in
match x.prev with
| None -> acc
| Some prev -> collect acc prev
in
on_dup uc name (collect [] last)
[@@inline never]
let find_single ?on_dup uc state name =
let res = Name_map.find state.unparsed name in
(match res with
| Some ({ prev = Some _; _ } as last) ->
multiple_occurrences uc name last ?on_dup
| _ -> ());
res
let field name ?default ?on_dup t (Fields (loc, _, uc)) state =
match find_single uc state name ?on_dup with
| Some { values; entry; _ } ->
let ctx = Values (Ast.loc entry, Some name, uc) in
let x = result ctx (t ctx values) in
(x, consume name state)
| None ->
match default with
| Some v -> (v, add_known name state)
| None -> field_missing loc name
let field_o name ?on_dup t (Fields (_, _, uc)) state =
match find_single uc state name ?on_dup with
| Some { values; entry; _ } ->
let ctx = Values (Ast.loc entry, Some name, uc) in
let x = result ctx (t ctx values) in
(Some x, consume name state)
| None ->
(None, add_known name state)
let field_b ?check ?on_dup name =
field name ~default:false ?on_dup
(Option.value check ~default:(return ()) >>= fun () ->
eos >>= function
| true -> return true
| _ -> bool)
let multi_field name t (Fields (_, _, uc)) state =
let rec loop acc field =
match field with
| None -> acc
| Some { values; prev; entry } ->
let ctx = Values (Ast.loc entry, Some name, uc) in
let x = result ctx (t ctx values) in
loop (x :: acc) prev
in
let res = loop [] (Name_map.find state.unparsed name) in
(res, consume name state)
let fields t (Values (loc, cstr, uc)) sexps =
let unparsed =
List.fold_left sexps ~init:Name_map.empty ~f:(fun acc sexp ->
match sexp with
| List (_, name_sexp :: values) -> begin
match name_sexp with
| Atom (_, A name) ->
Name_map.add acc name
{ values
; entry = sexp
; prev = Name_map.find acc name
}
| List (loc, _) | Quoted_string (loc, _) | Template { loc; _ } ->
of_sexp_error loc "Atom expected"
end
| _ ->
of_sexp_error (Ast.loc sexp)
"S-expression of the form (<name> <values>...) expected")
in
let ctx = Fields (loc, cstr, uc) in
let x = result ctx (t ctx { unparsed; known = [] }) in
(x, [])
let record t = enter (fields t)
type kind =
| Values of Loc.t * string option
| Fields of Loc.t * string option
let kind : type k. k context -> k -> kind * k
= fun ctx state ->
match ctx with
| Values (loc, cstr, _) -> (Values (loc, cstr), state)
| Fields (loc, cstr, _) -> (Fields (loc, cstr), state)
module Let_syntax = struct
let ( $ ) f t =
f >>= fun f ->
t >>| fun t ->
f t
let const = return
end
end
module type Sexpable = sig
type t
val dparse : t Of_sexp.t
val dgen : t To_sexp.t
end
let rec to_sexp = function
| Atom (A a) -> Sexp.Atom a
| List s -> List (List.map s ~f:to_sexp)
| Quoted_string s -> Sexp.Atom s
| Template t ->
List
[ Atom "template"
; Atom (Template.to_string ~syntax:Dune t)
]
module Io = struct
let load ?lexer path ~mode =
Io.with_lexbuf_from_file path ~f:(Parser.parse ~mode ?lexer)
end

410
src/dsexp/dsexp.mli Normal file
View File

@ -0,0 +1,410 @@
open! Stdune
(** Parsing of s-expressions.
This library is internal to jbuilder and guarantees no API stability.*)
type syntax = Jbuild | Dune
module Atom : sig
type t = private A of string [@@unboxed]
val is_valid : t -> syntax -> bool
val of_string : string -> t
val to_string : t -> string
val of_int : int -> t
val of_float : float -> t
val of_bool : bool -> t
val of_int64 : Int64.t -> t
val of_digest : Digest.t -> t
end
module Template : sig
type var_syntax = Dollar_brace | Dollar_paren | Percent
type var =
{ loc: Loc.t
; name: string
; payload: string option
; syntax: var_syntax
}
type part =
| Text of string
| Var of var
type t =
{ quoted: bool
; parts: part list
; loc: Loc.t
}
val string_of_var : var -> string
val to_string : t -> syntax:syntax -> string
val remove_locs : t -> t
end
(** The S-expression type *)
type t =
| Atom of Atom.t
| Quoted_string of string
| List of t list
| Template of Template.t
val atom : string -> t
(** [atom s] convert the string [s] to an Atom.
@raise Invalid_argument if [s] does not satisfy [Atom.is_valid s]. *)
val atom_or_quoted_string : string -> t
val unsafe_atom_of_string : string -> t
(** Serialize a S-expression *)
val to_string : t -> syntax:syntax -> string
(** Serialize a S-expression using indentation to improve readability *)
val pp : syntax -> Format.formatter -> t -> unit
(** Serialization that never fails because it quotes atoms when necessary
TODO remove this once we have a proper sexp type *)
val pp_quoted : Format.formatter -> t -> unit
(** Same as [pp ~syntax:Dune], but split long strings. The formatter
must have been prepared with [prepare_formatter]. *)
val pp_split_strings : Format.formatter -> t -> unit
(** Prepare a formatter for [pp_split_strings]. Additionaly the
formatter escape newlines when the tags "makefile-action" or
"makefile-stuff" are active. *)
val prepare_formatter : Format.formatter -> unit
(** Abstract syntax tree *)
module Ast : sig
type sexp = t
type t =
| Atom of Loc.t * Atom.t
| Quoted_string of Loc.t * string
| Template of Template.t
| List of Loc.t * t list
val atom_or_quoted_string : Loc.t -> string -> t
val loc : t -> Loc.t
val remove_locs : t -> sexp
end with type sexp := t
val add_loc : t -> loc:Loc.t -> Ast.t
module Parse_error : sig
type t
val loc : t -> Loc.t
val message : t -> string
end
(** Exception raised in case of a parsing error *)
exception Parse_error of Parse_error.t
module Lexer : sig
module Token : sig
type t =
| Atom of Atom.t
| Quoted_string of string
| Lparen
| Rparen
| Sexp_comment
| Eof
| Template of Template.t
end
type t = Lexing.lexbuf -> Token.t
val token : t
val jbuild_token : t
end
module Parser : sig
module Mode : sig
type 'a t =
| Single : Ast.t t
| Many : Ast.t list t
| Many_as_one : Ast.t t
end
val parse
: mode:'a Mode.t
-> ?lexer:Lexer.t
-> Lexing.lexbuf
-> 'a
end
val parse_string
: fname:string
-> mode:'a Parser.Mode.t
-> ?lexer:Lexer.t
-> string
-> 'a
module To_sexp : sig
type sexp = t
include Sexp_intf.Combinators with type 'a t = 'a -> t
val record : (string * sexp) list -> sexp
type field
val field
: string
-> 'a t
-> ?equal:('a -> 'a -> bool)
-> ?default:'a
-> 'a
-> field
val field_o : string -> 'a t-> 'a option -> field
val record_fields : field list t
val unknown : _ t
end with type sexp := t
module Of_sexp : sig
type ast = Ast.t =
| Atom of Loc.t * Atom.t
| Quoted_string of Loc.t * string
| Template of Template.t
| List of Loc.t * ast list
type hint =
{ on: string
; candidates: string list
}
exception Of_sexp of Loc.t * string * hint option
(** Monad producing a value of type ['a] by parsing an input
composed of a sequence of S-expressions.
The input can be seen either as a plain sequence of
S-expressions or a list of fields. The ['kind] parameter
indicates how the input is seen:
- with {['kind = [values]]}, the input is seen as an ordered
sequence of S-expressions
- with {['kind = [fields]]}, the input is seen as an unordered
sequence of fields
A field is a S-expression of the form: [(<atom> <values>...)]
where [atom] is a plain atom, i.e. not a quoted string and not
containing variables. [values] is a sequence of zero, one or more
S-expressions.
It is possible to switch between the two mode at any time using
the appropriate combinator. Some primitives can be used in both
mode while some are specific to one mode. *)
type ('a, 'kind) parser
type values
type fields
type 'a t = ('a, values) parser
type 'a fields_parser = ('a, fields) parser
(** [parse parser context sexp] parse a S-expression using the
following parser. The input consist of a single
S-expression. [context] allows to pass extra information such as
versions to individual parsers. *)
val parse : 'a t -> Univ_map.t -> ast -> 'a
val return : 'a -> ('a, _) parser
val (>>=) : ('a, 'k) parser -> ('a -> ('b, 'k) parser) -> ('b, 'k) parser
val (>>|) : ('a, 'k) parser -> ('a -> 'b) -> ('b, 'k) parser
val (>>>) : (unit, 'k) parser -> ('a, 'k) parser -> ('a, 'k) parser
val map : ('a, 'k) parser -> f:('a -> 'b) -> ('b, 'k) parser
val try_ : ('a, 'k) parser -> (exn -> ('a, 'k) parser) -> ('a, 'k) parser
(** Access to the context *)
val get : 'a Univ_map.Key.t -> ('a option, _) parser
val set : 'a Univ_map.Key.t -> 'a -> ('b, 'k) parser -> ('b, 'k) parser
val get_all : (Univ_map.t, _) parser
val set_many : Univ_map.t -> ('a, 'k) parser -> ('a, 'k) parser
(** Return the location of the list currently being parsed. *)
val loc : (Loc.t, _) parser
(** End of sequence condition. Uses [then_] if there are no more
S-expressions to parse, [else_] otherwise. *)
val if_eos : then_:('a, 'b) parser -> else_:('a, 'b) parser -> ('a, 'b) parser
(** If the next element of the sequence is a list, parse it with
[then_], otherwise parse it with [else_]. *)
val if_list
: then_:'a t
-> else_:'a t
-> 'a t
(** If the next element of the sequence is of the form [(:<name>
...)], use [then_] to parse [...]. Otherwise use [else_]. *)
val if_paren_colon_form
: then_:(Loc.t * string -> 'a) t
-> else_:'a t
-> 'a t
(** Expect the next element to be the following atom. *)
val keyword : string -> unit t
(** {[match_keyword [(k1, t1); (k2, t2); ...] ~fallback]} inspects
the next element of the input sequence. If it is an atom equal to
one of [k1], [k2], ... then the corresponding parser is used to
parse the rest of the sequence. Other [fallback] is used. *)
val match_keyword
: (string * 'a t) list
-> fallback:'a t
-> 'a t
(** Use [before] to parse elements until the keyword is
reached. Then use [after] to parse the rest. *)
val until_keyword
: string
-> before:'a t
-> after:'b t
-> ('a list * 'b option) t
(** What is currently being parsed. The second argument is the atom
at the beginnig of the list when inside a [sum ...] or [field
...]. *)
type kind =
| Values of Loc.t * string option
| Fields of Loc.t * string option
val kind : (kind, _) parser
(** [repeat t] use [t] to consume all remaning elements of the input
until the end of sequence is reached. *)
val repeat : 'a t -> 'a list t
(** Capture the rest of the input for later parsing *)
val capture : ('a t -> 'a) t
(** [enter t] expect the next element of the input to be a list and
parse its contents with [t]. *)
val enter : 'a t -> 'a t
(** [fields fp] converts the rest of the current input to a list of
fields and parse them with [fp]. This operation fails if one the
S-expression in the input is not of the form [(<atom>
<values>...)] *)
val fields : 'a fields_parser -> 'a t
(** [record fp = enter (fields fp)] *)
val record : 'a fields_parser -> 'a t
(** Consume the next element of the input as a string, int, char, ... *)
include Sexp_intf.Combinators with type 'a t := 'a t
(** Unparsed next element of the input *)
val raw : ast t
(** Inspect the next element of the input without consuming it *)
val peek : ast option t
(** Same as [peek] but fail if the end of input is reached *)
val peek_exn : ast t
(** Consume and ignore the next element of the input *)
val junk : unit t
(** Ignore all the rest of the input *)
val junk_everything : (unit, _) parser
(** [plain_string f] expects the next element of the input to be a
plain string, i.e. either an atom or a quoted string, but not a
template nor a list. *)
val plain_string : (loc:Loc.t -> string -> 'a) -> 'a t
val fix : ('a t -> 'a t) -> 'a t
val of_sexp_error
: ?hint:hint
-> Loc.t
-> string
-> _
val of_sexp_errorf
: ?hint:hint
-> Loc.t
-> ('a, unit, string, 'b) format4
-> 'a
val no_templates
: ?hint:hint
-> Loc.t
-> ('a, unit, string, 'b) format4
-> 'a
val located : ('a, 'k) parser -> (Loc.t * 'a, 'k) parser
val enum : (string * 'a) list -> 'a t
(** Parser that parse a S-expression of the form [(<atom> <s-exp1>
<s-exp2> ...)] or [<atom>]. [<atom>] is looked up in the list and
the remaining s-expressions are parsed using the corresponding
list parser. *)
val sum : (string * 'a t) list -> 'a t
(** Check the result of a list parser, and raise a properly located
error in case of failure. *)
val map_validate
: 'a fields_parser
-> f:('a -> ('b, string) Result.t)
-> 'b fields_parser
(** {3 Parsing record fields} *)
val field
: string
-> ?default:'a
-> ?on_dup:(Univ_map.t -> string -> Ast.t list -> unit)
-> 'a t
-> 'a fields_parser
val field_o
: string
-> ?on_dup:(Univ_map.t -> string -> Ast.t list -> unit)
-> 'a t
-> 'a option fields_parser
val field_b
: ?check:(unit t)
-> ?on_dup:(Univ_map.t -> string -> Ast.t list -> unit)
-> string
-> bool fields_parser
(** A field that can appear multiple times *)
val multi_field
: string
-> 'a t
-> 'a list fields_parser
(** Default value for [on_dup]. It fails with an appropriate error
message. *)
val field_present_too_many_times : Univ_map.t -> string -> Ast.t list -> _
module Let_syntax : sig
val ( $ ) : ('a -> 'b, 'k) parser -> ('a, 'k) parser -> ('b, 'k) parser
val const : 'a -> ('a, _) parser
end
end
module type Sexpable = sig
type t
val dparse : t Of_sexp.t
val dgen : t To_sexp.t
end
val to_sexp : t Sexp.To_sexp.t
module Io : sig
val load : ?lexer:Lexer.t -> Path.t -> mode:'a Parser.Mode.t -> 'a
end

View File

@ -1,6 +1,7 @@
(library (library
(name usexp) (name dsexp)
(synopsis "[Internal] S-expression library") (synopsis "[Internal] S-expression library")
(public_name dune._usexp)) (libraries stdune)
(public_name dune._dsexp))
(ocamllex dune_lexer jbuild_lexer) (ocamllex dune_lexer jbuild_lexer)

View File

@ -1,4 +1,5 @@
{ {
open! Stdune
open Lexer_shared open Lexer_shared
type block_string_line_kind = type block_string_line_kind =

View File

@ -1,4 +1,4 @@
open Import open! Stdune
let quote_length s ~syntax = let quote_length s ~syntax =
let n = ref 0 in let n = ref 0 in

View File

@ -1,4 +1,4 @@
open Import open! Stdune
include Types.Template include Types.Template
@ -76,7 +76,7 @@ let pp_split_strings ppf (t : t) =
| Var s -> | Var s ->
Format.pp_print_string ppf (string_of_var s) Format.pp_print_string ppf (string_of_var s)
| Text s -> | Text s ->
begin match String.split_on_char s ~on:'\n' with begin match String.split s ~on:'\n' with
| [] -> assert false | [] -> assert false
| [s] -> Format.pp_print_string ppf (Escape.escaped ~syntax s) | [s] -> Format.pp_print_string ppf (Escape.escaped ~syntax s)
| split -> | split ->

View File

@ -1,3 +1,5 @@
open! Stdune
type var_syntax = Types.Template.var_syntax = type var_syntax = Types.Template.var_syntax =
| Dollar_brace | Dollar_brace
| Dollar_paren | Dollar_paren

View File

@ -1,3 +1,5 @@
open! Stdune
module Template = struct module Template = struct
type var_syntax = Dollar_brace | Dollar_paren | Percent type var_syntax = Dollar_brace | Dollar_paren | Percent
@ -18,11 +20,3 @@ module Template = struct
; loc: Loc.t ; loc: Loc.t
} }
end end
module Sexp = struct
type t =
| Atom of Atom.t
| Quoted_string of string
| List of t list
| Template of Template.t
end

View File

@ -6,7 +6,7 @@
xdg xdg
re re
opam_file_format opam_file_format
usexp dsexp
ocaml_config ocaml_config
which_program) which_program)
(synopsis "Internal Dune library, do not use!") (synopsis "Internal Dune library, do not use!")

View File

@ -1,3 +1,4 @@
open! Stdune
type stanza = Stanza.t = .. type stanza = Stanza.t = ..
module Stanza = struct module Stanza = struct
@ -36,7 +37,7 @@ module Stanza = struct
in in
(pat, configs)) (pat, configs))
let t = let dparse =
let%map () = Syntax.since Stanza.syntax (1, 0) let%map () = Syntax.since Stanza.syntax (1, 0)
and loc = loc and loc = loc
and rules = repeat rule and rules = repeat rule

View File

@ -1,4 +1,4 @@
open Import open! Stdune
type stanza = Stanza.t = .. type stanza = Stanza.t = ..
@ -18,7 +18,7 @@ module Stanza : sig
; rules : (pattern * config) list ; rules : (pattern * config) list
} }
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
end end
type stanza += type stanza +=

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Stanza.Of_sexp open Stanza.Of_sexp
@ -10,7 +11,7 @@ module Jbuild_version = struct
type t = type t =
| V1 | V1
let t = let dparse =
enum enum
[ "1", V1 [ "1", V1
] ]
@ -53,7 +54,7 @@ module Lib_name : sig
val validate : (Loc.t * result) -> wrapped:bool -> t val validate : (Loc.t * result) -> wrapped:bool -> t
val t : (Loc.t * result) Sexp.Of_sexp.t val dparse : (Loc.t * result) Dsexp.Of_sexp.t
end = struct end = struct
type t = string type t = string
@ -78,9 +79,9 @@ end = struct
let validate (loc, res) ~wrapped = let validate (loc, res) ~wrapped =
match res, wrapped with match res, wrapped with
| Ok s, _ -> s | Ok s, _ -> s
| Warn _, true -> Loc.fail loc "%s" wrapped_message | Warn _, true -> Errors.fail loc "%s" wrapped_message
| Warn s, false -> Loc.warn loc "%s" wrapped_message; s | Warn s, false -> Errors.warn loc "%s" wrapped_message; s
| Invalid, _ -> Loc.fail loc "%s" invalid_message | Invalid, _ -> Errors.fail loc "%s" invalid_message
let valid_char = function let valid_char = function
| 'A'..'Z' | 'a'..'z' | '_' | '0'..'9' -> true | 'A'..'Z' | 'a'..'z' | '_' | '0'..'9' -> true
@ -110,7 +111,7 @@ end = struct
in in
loop false 0 loop false 0
let t = plain_string (fun ~loc s -> (loc, of_string s)) let dparse = plain_string (fun ~loc s -> (loc, of_string s))
end end
let file = let file =
@ -210,12 +211,12 @@ module Pkg = struct
(hint name_s (Package.Name.Map.keys packages (hint name_s (Package.Name.Map.keys packages
|> List.map ~f:Package.Name.to_string))) |> List.map ~f:Package.Name.to_string)))
let t = let dparse =
let%map p = Dune_project.get_exn () let%map p = Dune_project.get_exn ()
and (loc, name) = located Package.Name.t in and (loc, name) = located Package.Name.dparse in
match resolve p name with match resolve p name with
| Ok x -> x | Ok x -> x
| Error e -> Loc.fail loc "%s" e | Error e -> Errors.fail loc "%s" e
let field stanza = let field stanza =
map_validate map_validate
@ -266,11 +267,11 @@ module Pps_and_flags = struct
in in
(pps, List.concat flags) (pps, List.concat flags)
let t = list item >>| split let dparse = list item >>| split
end end
module Dune_syntax = struct module Dune_syntax = struct
let t = let dparse =
let%map l, flags = let%map l, flags =
until_keyword "--" until_keyword "--"
~before:(plain_string (fun ~loc s -> (loc, s))) ~before:(plain_string (fun ~loc s -> (loc, s)))
@ -286,10 +287,10 @@ module Pps_and_flags = struct
(pps, more_flags @ Option.value flags ~default:[]) (pps, more_flags @ Option.value flags ~default:[])
end end
let t = let dparse =
switch_file_kind switch_file_kind
~jbuild:Jbuild_syntax.t ~jbuild:Jbuild_syntax.dparse
~dune:Dune_syntax.t ~dune:Dune_syntax.dparse
end end
module Bindings = struct module Bindings = struct
@ -301,6 +302,11 @@ module Bindings = struct
let fold t ~f ~init = List.fold_left ~f:(fun acc x -> f x acc) ~init t let fold t ~f ~init = List.fold_left ~f:(fun acc x -> f x acc) ~init t
let map t ~f =
List.map t ~f:(function
| Unnamed a -> Unnamed (f a)
| Named (s, xs) -> Named (s, List.map ~f xs))
let to_list = let to_list =
List.concat_map ~f:(function List.concat_map ~f:(function
| Unnamed x -> [x] | Unnamed x -> [x]
@ -344,17 +350,25 @@ module Bindings = struct
in in
loop String.Set.empty [] l) loop String.Set.empty [] l)
let t elem = let dparse elem =
switch_file_kind switch_file_kind
~jbuild:(jbuild elem) ~jbuild:(jbuild elem)
~dune:(dune elem) ~dune:(dune elem)
let sexp_of_t sexp_of_a bindings = let dgen dgen bindings =
Dsexp.List (
List.map bindings ~f:(function
| Unnamed a -> dgen a
| Named (name, bindings) ->
Dsexp.List (Dsexp.atom (":" ^ name) :: List.map ~f:dgen bindings))
)
let to_sexp sexp_of_a bindings =
Sexp.List ( Sexp.List (
List.map bindings ~f:(function List.map bindings ~f:(function
| Unnamed a -> sexp_of_a a | Unnamed a -> sexp_of_a a
| Named (name, bindings) -> | Named (name, bindings) ->
Sexp.List (Sexp.atom (":" ^ name) :: List.map ~f:sexp_of_a bindings)) Sexp.List (Sexp.To_sexp.string (":" ^ name) :: List.map ~f:sexp_of_a bindings))
) )
end end
@ -368,9 +382,18 @@ module Dep_conf = struct
| Package of String_with_vars.t | Package of String_with_vars.t
| Universe | Universe
let t = let remove_locs = function
let t = | File sw -> File (String_with_vars.remove_locs sw)
let sw = String_with_vars.t in | Alias sw -> Alias (String_with_vars.remove_locs sw)
| Alias_rec sw -> Alias_rec (String_with_vars.remove_locs sw)
| Glob_files sw -> Glob_files (String_with_vars.remove_locs sw)
| Source_tree sw -> Source_tree (String_with_vars.remove_locs sw)
| Package sw -> Package (String_with_vars.remove_locs sw)
| Universe -> Universe
let dparse =
let dparse =
let sw = String_with_vars.dparse in
sum sum
[ "file" , (sw >>| fun x -> File x) [ "file" , (sw >>| fun x -> File x)
; "alias" , (sw >>| fun x -> Alias x) ; "alias" , (sw >>| fun x -> Alias x)
@ -390,31 +413,33 @@ module Dep_conf = struct
] ]
in in
if_list if_list
~then_:t ~then_:dparse
~else_:(String_with_vars.t >>| fun x -> File x) ~else_:(String_with_vars.dparse >>| fun x -> File x)
open Sexp open Dsexp
let sexp_of_t = function let dgen = function
| File t -> | File t ->
List [ Sexp.unsafe_atom_of_string "file" List [ Dsexp.unsafe_atom_of_string "file"
; String_with_vars.sexp_of_t t ] ; String_with_vars.dgen t ]
| Alias t -> | Alias t ->
List [ Sexp.unsafe_atom_of_string "alias" List [ Dsexp.unsafe_atom_of_string "alias"
; String_with_vars.sexp_of_t t ] ; String_with_vars.dgen t ]
| Alias_rec t -> | Alias_rec t ->
List [ Sexp.unsafe_atom_of_string "alias_rec" List [ Dsexp.unsafe_atom_of_string "alias_rec"
; String_with_vars.sexp_of_t t ] ; String_with_vars.dgen t ]
| Glob_files t -> | Glob_files t ->
List [ Sexp.unsafe_atom_of_string "glob_files" List [ Dsexp.unsafe_atom_of_string "glob_files"
; String_with_vars.sexp_of_t t ] ; String_with_vars.dgen t ]
| Source_tree t -> | Source_tree t ->
List [ Sexp.unsafe_atom_of_string "files_recursively_in" List [ Dsexp.unsafe_atom_of_string "files_recursively_in"
; String_with_vars.sexp_of_t t ] ; String_with_vars.dgen t ]
| Package t -> | Package t ->
List [ Sexp.unsafe_atom_of_string "package" List [ Dsexp.unsafe_atom_of_string "package"
; String_with_vars.sexp_of_t t] ; String_with_vars.dgen t]
| Universe -> | Universe ->
Sexp.unsafe_atom_of_string "universe" Dsexp.unsafe_atom_of_string "universe"
let to_sexp t = Dsexp.to_sexp (dgen t)
end end
module Preprocess = struct module Preprocess = struct
@ -429,20 +454,20 @@ module Preprocess = struct
| Action of Loc.t * Action.Unexpanded.t | Action of Loc.t * Action.Unexpanded.t
| Pps of pps | Pps of pps
let t = let dparse =
sum sum
[ "no_preprocessing", return No_preprocessing [ "no_preprocessing", return No_preprocessing
; "action", ; "action",
(located Action.Unexpanded.t >>| fun (loc, x) -> (located Action.Unexpanded.dparse >>| fun (loc, x) ->
Action (loc, x)) Action (loc, x))
; "pps", ; "pps",
(let%map loc = loc (let%map loc = loc
and pps, flags = Pps_and_flags.t in and pps, flags = Pps_and_flags.dparse in
Pps { loc; pps; flags; staged = false }) Pps { loc; pps; flags; staged = false })
; "staged_pps", ; "staged_pps",
(let%map () = Syntax.since Stanza.syntax (1, 1) (let%map () = Syntax.since Stanza.syntax (1, 1)
and loc = loc and loc = loc
and pps, flags = Pps_and_flags.t in and pps, flags = Pps_and_flags.dparse in
Pps { loc; pps; flags; staged = true }) Pps { loc; pps; flags; staged = true })
] ]
@ -464,36 +489,36 @@ module Blang = struct
; "<>", Neq ; "<>", Neq
] ]
let t = let dparse =
let ops = let ops =
List.map ops ~f:(fun (name, op) -> List.map ops ~f:(fun (name, op) ->
( name ( name
, (let%map x = String_with_vars.t , (let%map x = String_with_vars.dparse
and y = String_with_vars.t and y = String_with_vars.dparse
in in
Compare (op, x, y)))) Compare (op, x, y))))
in in
let t = let dparse =
fix begin fun (t : String_with_vars.t Blang.t Sexp.Of_sexp.t) -> fix begin fun (t : String_with_vars.t Blang.t Dsexp.Of_sexp.t) ->
if_list if_list
~then_:( ~then_:(
[ "or", repeat t >>| (fun x -> Or x) [ "or", repeat t >>| (fun x -> Or x)
; "and", repeat t >>| (fun x -> And x) ; "and", repeat t >>| (fun x -> And x)
] @ ops ] @ ops
|> sum) |> sum)
~else_:(String_with_vars.t >>| fun v -> Expr v) ~else_:(String_with_vars.dparse >>| fun v -> Expr v)
end end
in in
let%map () = Syntax.since Stanza.syntax (1, 1) let%map () = Syntax.since Stanza.syntax (1, 1)
and t = t and dparse = dparse
in in
t dparse
end end
module Per_module = struct module Per_module = struct
include Per_item.Make(Module.Name) include Per_item.Make(Module.Name)
let t ~default a = let dparse ~default a =
peek_exn >>= function peek_exn >>= function
| List (loc, Atom (_, A "per_module") :: _) -> | List (loc, Atom (_, A "per_module") :: _) ->
sum [ "per_module", sum [ "per_module",
@ -517,7 +542,7 @@ end
module Preprocess_map = struct module Preprocess_map = struct
type t = Preprocess.t Per_module.t type t = Preprocess.t Per_module.t
let t = Per_module.t Preprocess.t ~default:Preprocess.No_preprocessing let dparse = Per_module.dparse Preprocess.dparse ~default:Preprocess.No_preprocessing
let no_preprocessing = Per_module.for_all Preprocess.No_preprocessing let no_preprocessing = Per_module.for_all Preprocess.No_preprocessing
@ -537,7 +562,7 @@ end
module Lint = struct module Lint = struct
type t = Preprocess_map.t type t = Preprocess_map.t
let t = Preprocess_map.t let dparse = Preprocess_map.dparse
let default = Preprocess_map.default let default = Preprocess_map.default
let no_lint = default let no_lint = default
@ -552,7 +577,7 @@ module Js_of_ocaml = struct
; javascript_files : string list ; javascript_files : string list
} }
let t = let dparse =
record record
(let%map flags = field_oslu "flags" (let%map flags = field_oslu "flags"
and javascript_files = field "javascript_files" (list string) ~default:[] and javascript_files = field "javascript_files" (list string) ~default:[]
@ -617,7 +642,7 @@ module Lib_dep = struct
in in
loop String.Set.empty String.Set.empty preds) loop String.Set.empty String.Set.empty preds)
let t = let dparse =
if_list if_list
~then_:( ~then_:(
enter enter
@ -649,9 +674,9 @@ module Lib_deps = struct
| Optional | Optional
| Forbidden | Forbidden
let t = let dparse =
let%map loc = loc let%map loc = loc
and t = repeat Lib_dep.t and t = repeat Lib_dep.dparse
in in
let add kind name acc = let add kind name acc =
match String.Map.find acc name with match String.Map.find acc name with
@ -686,7 +711,7 @@ module Lib_deps = struct
: kind String.Map.t); : kind String.Map.t);
t t
let t = parens_removed_in_dune t let dparse = parens_removed_in_dune dparse
let of_pps pps = let of_pps pps =
List.map pps ~f:(fun pp -> Lib_dep.of_pp (Loc.none, pp)) List.map pps ~f:(fun pp -> Lib_dep.of_pp (Loc.none, pp))
@ -720,22 +745,22 @@ module Buildable = struct
let modules_field name = Ordered_set_lang.field name let modules_field name = Ordered_set_lang.field name
let t = let dparse =
let%map loc = loc let%map loc = loc
and preprocess = and preprocess =
field "preprocess" Preprocess_map.t ~default:Preprocess_map.default field "preprocess" Preprocess_map.dparse ~default:Preprocess_map.default
and preprocessor_deps = and preprocessor_deps =
field "preprocessor_deps" (list Dep_conf.t) ~default:[] field "preprocessor_deps" (list Dep_conf.dparse) ~default:[]
and lint = field "lint" Lint.t ~default:Lint.default and lint = field "lint" Lint.dparse ~default:Lint.default
and modules = modules_field "modules" and modules = modules_field "modules"
and modules_without_implementation = and modules_without_implementation =
modules_field "modules_without_implementation" modules_field "modules_without_implementation"
and libraries = field "libraries" Lib_deps.t ~default:[] and libraries = field "libraries" Lib_deps.dparse ~default:[]
and flags = field_oslu "flags" and flags = field_oslu "flags"
and ocamlc_flags = field_oslu "ocamlc_flags" and ocamlc_flags = field_oslu "ocamlc_flags"
and ocamlopt_flags = field_oslu "ocamlopt_flags" and ocamlopt_flags = field_oslu "ocamlopt_flags"
and js_of_ocaml = and js_of_ocaml =
field "js_of_ocaml" Js_of_ocaml.t ~default:Js_of_ocaml.default field "js_of_ocaml" Js_of_ocaml.dparse ~default:Js_of_ocaml.default
and allow_overlapping_dependencies = and allow_overlapping_dependencies =
field_b "allow_overlapping_dependencies" field_b "allow_overlapping_dependencies"
in in
@ -803,7 +828,7 @@ module Sub_system_info = struct
val name : Sub_system_name.t val name : Sub_system_name.t
val loc : t -> Loc.t val loc : t -> Loc.t
val syntax : Syntax.t val syntax : Syntax.t
val parse : t Sexp.Of_sexp.t val parse : t Dsexp.Of_sexp.t
end end
let all = Sub_system_name.Table.create ~default_value:None let all = Sub_system_name.Table.create ~default_value:None
@ -846,7 +871,7 @@ module Mode_conf = struct
end end
include T include T
let t = let dparse =
enum enum
[ "byte" , Byte [ "byte" , Byte
; "native", Native ; "native", Native
@ -861,13 +886,13 @@ module Mode_conf = struct
let pp fmt t = let pp fmt t =
Format.pp_print_string fmt (to_string t) Format.pp_print_string fmt (to_string t)
let sexp_of_t t = let dgen t =
Sexp.unsafe_atom_of_string (to_string t) Dsexp.unsafe_atom_of_string (to_string t)
module Set = struct module Set = struct
include Set.Make(T) include Set.Make(T)
let t = list t >>| of_list let dparse = list dparse >>| of_list
let default = of_list [Byte; Best] let default = of_list [Byte; Best]
@ -886,7 +911,7 @@ module Library = struct
| Ppx_deriver | Ppx_deriver
| Ppx_rewriter | Ppx_rewriter
let t = let dparse =
enum enum
[ "normal" , Normal [ "normal" , Normal
; "ppx_deriver" , Ppx_deriver ; "ppx_deriver" , Ppx_deriver
@ -920,11 +945,11 @@ module Library = struct
; dune_version : Syntax.Version.t ; dune_version : Syntax.Version.t
} }
let t = let dparse =
record record
(let%map buildable = Buildable.t (let%map buildable = Buildable.dparse
and loc = loc and loc = loc
and name = field_o "name" Lib_name.t and name = field_o "name" Lib_name.dparse
and public = Public_lib.public_name_field and public = Public_lib.public_name_field
and synopsis = field_o "synopsis" string and synopsis = field_o "synopsis" string
and install_c_headers = and install_c_headers =
@ -939,8 +964,8 @@ module Library = struct
and c_library_flags = field_oslu "c_library_flags" and c_library_flags = field_oslu "c_library_flags"
and virtual_deps = and virtual_deps =
field "virtual_deps" (list (located string)) ~default:[] field "virtual_deps" (list (located string)) ~default:[]
and modes = field "modes" Mode_conf.Set.t ~default:Mode_conf.Set.default and modes = field "modes" Mode_conf.Set.dparse ~default:Mode_conf.Set.default
and kind = field "kind" Kind.t ~default:Kind.Normal and kind = field "kind" Kind.dparse ~default:Kind.Normal
and wrapped = field "wrapped" bool ~default:true and wrapped = field "wrapped" bool ~default:true
and optional = field_b "optional" and optional = field_b "optional"
and self_build_stubs_archive = and self_build_stubs_archive =
@ -1038,7 +1063,7 @@ module Install_conf = struct
| List (_, [Atom (_, A src); Atom (_, A "as"); Atom (_, A dst)]) -> | List (_, [Atom (_, A src); Atom (_, A "as"); Atom (_, A dst)]) ->
junk >>> return { src; dst = Some dst } junk >>> return { src; dst = Some dst }
| sexp -> | sexp ->
of_sexp_error (Sexp.Ast.loc sexp) of_sexp_error (Dsexp.Ast.loc sexp)
"invalid format, <name> or (<name> as <install-as>) expected" "invalid format, <name> or (<name> as <install-as>) expected"
type t = type t =
@ -1047,9 +1072,9 @@ module Install_conf = struct
; package : Package.t ; package : Package.t
} }
let t = let dparse =
record record
(let%map section = field "section" Install.Section.t (let%map section = field "section" Install.Section.dparse
and files = field "files" (list file) and files = field "files" (list file)
and package = Pkg.field "install" and package = Pkg.field "install"
in in
@ -1105,37 +1130,37 @@ module Executables = struct
] ]
let simple = let simple =
Sexp.Of_sexp.enum simple_representations Dsexp.Of_sexp.enum simple_representations
let t = let dparse =
if_list if_list
~then_: ~then_:
(enter (enter
(let%map mode = Mode_conf.t (let%map mode = Mode_conf.dparse
and kind = Binary_kind.t in and kind = Binary_kind.dparse in
{ mode; kind })) { mode; kind }))
~else_:simple ~else_:simple
let simple_sexp_of_t link_mode = let simple_dgen link_mode =
let is_ok (_, candidate) = let is_ok (_, candidate) =
compare candidate link_mode = Eq compare candidate link_mode = Eq
in in
match List.find ~f:is_ok simple_representations with match List.find ~f:is_ok simple_representations with
| Some (s, _) -> Some (Sexp.unsafe_atom_of_string s) | Some (s, _) -> Some (Dsexp.unsafe_atom_of_string s)
| None -> None | None -> None
let sexp_of_t link_mode = let dgen link_mode =
match simple_sexp_of_t link_mode with match simple_dgen link_mode with
| Some s -> s | Some s -> s
| None -> | None ->
let { mode; kind } = link_mode in let { mode; kind } = link_mode in
Sexp.To_sexp.pair Mode_conf.sexp_of_t Binary_kind.sexp_of_t (mode, kind) Dsexp.To_sexp.pair Mode_conf.dgen Binary_kind.dgen (mode, kind)
module Set = struct module Set = struct
include Set.Make(T) include Set.Make(T)
let t = let dparse =
located (list t) >>| fun (loc, l) -> located (list dparse) >>| fun (loc, l) ->
match l with match l with
| [] -> of_sexp_errorf loc "No linking mode defined" | [] -> of_sexp_errorf loc "No linking mode defined"
| l -> | l ->
@ -1175,12 +1200,12 @@ module Executables = struct
s s
let common = let common =
let%map buildable = Buildable.t let%map buildable = Buildable.dparse
and (_ : bool) = field "link_executables" ~default:true and (_ : bool) = field "link_executables" ~default:true
(Syntax.deleted_in Stanza.syntax (1, 0) >>> bool) (Syntax.deleted_in Stanza.syntax (1, 0) >>> bool)
and link_deps = field "link_deps" (list Dep_conf.t) ~default:[] and link_deps = field "link_deps" (list Dep_conf.dparse) ~default:[]
and link_flags = field_oslu "link_flags" and link_flags = field_oslu "link_flags"
and modes = field "modes" Link_mode.Set.t ~default:Link_mode.Set.default and modes = field "modes" Link_mode.Set.dparse ~default:Link_mode.Set.default
and () = map_validate and () = map_validate
(field "inline_tests" (repeat junk >>| fun _ -> true) ~default:false) (field "inline_tests" (repeat junk >>| fun _ -> true) ~default:false)
~f:(function ~f:(function
@ -1240,9 +1265,9 @@ module Executables = struct
match Link_mode.Set.best_install_mode t.modes with match Link_mode.Set.best_install_mode t.modes with
| None when has_public_name -> | None when has_public_name ->
let mode_to_string mode = let mode_to_string mode =
" - " ^ Sexp.to_string ~syntax:Dune (Link_mode.sexp_of_t mode) in " - " ^ Dsexp.to_string ~syntax:Dune (Link_mode.dgen mode) in
let mode_strings = List.map ~f:mode_to_string Link_mode.installable_modes in let mode_strings = List.map ~f:mode_to_string Link_mode.installable_modes in
Loc.fail Errors.fail
buildable.loc buildable.loc
"No installable mode found for %s.\n\ "No installable mode found for %s.\n\
One of the following modes is required:\n\ One of the following modes is required:\n\
@ -1278,8 +1303,8 @@ module Executables = struct
| Some (loc, _) -> | Some (loc, _) ->
let func = let func =
match file_kind with match file_kind with
| Jbuild -> Loc.warn | Jbuild -> Errors.warn
| Dune -> Loc.fail | Dune -> Errors.fail
in in
func loc func loc
"This field is useless without a (public_name%s ...) field." "This field is useless without a (public_name%s ...) field."
@ -1358,7 +1383,7 @@ module Rule = struct
| Not_a_rule_stanza | Not_a_rule_stanza
| Ignore_source_files | Ignore_source_files
let t = let dparse =
enum enum
[ "standard" , Standard [ "standard" , Standard
; "fallback" , Fallback ; "fallback" , Fallback
@ -1366,7 +1391,7 @@ module Rule = struct
; "promote-until-clean", Promote_but_delete_on_clean ; "promote-until-clean", Promote_but_delete_on_clean
] ]
let field = field "mode" t ~default:Standard let field = field "mode" dparse ~default:Standard
end end
type t = type t =
@ -1411,7 +1436,7 @@ module Rule = struct
] ]
let short_form = let short_form =
located Action.Unexpanded.t >>| fun (loc, action) -> located Action.Unexpanded.dparse >>| fun (loc, action) ->
{ targets = Infer { targets = Infer
; deps = Bindings.empty ; deps = Bindings.empty
; action = (loc, action) ; action = (loc, action)
@ -1422,10 +1447,11 @@ module Rule = struct
let long_form = let long_form =
let%map loc = loc let%map loc = loc
and action = field "action" (located Action.Unexpanded.t) and action = field "action" (located Action.Unexpanded.dparse)
and targets = field "targets" (list file_in_current_dir) and targets = field "targets" (list file_in_current_dir)
and deps = field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty and deps =
and locks = field "locks" (list String_with_vars.t) ~default:[] field "deps" (Bindings.dparse Dep_conf.dparse) ~default:Bindings.empty
and locks = field "locks" (list String_with_vars.dparse) ~default:[]
and mode = and mode =
map_validate map_validate
(let%map fallback = (let%map fallback =
@ -1433,7 +1459,7 @@ module Rule = struct
~check:(Syntax.renamed_in Stanza.syntax (1, 0) ~check:(Syntax.renamed_in Stanza.syntax (1, 0)
~to_:"(mode fallback)") ~to_:"(mode fallback)")
"fallback" "fallback"
and mode = field_o "mode" Mode.t and mode = field_o "mode" Mode.dparse
in in
(fallback, mode)) (fallback, mode))
~f:(function ~f:(function
@ -1472,10 +1498,10 @@ module Rule = struct
| Some Action -> short_form | Some Action -> short_form
end end
| sexp -> | sexp ->
of_sexp_errorf (Sexp.Ast.loc sexp) of_sexp_errorf (Dsexp.Ast.loc sexp)
"S-expression of the form (<atom> ...) expected" "S-expression of the form (<atom> ...) expected"
let t = let dparse =
switch_file_kind switch_file_kind
~jbuild:jbuild_syntax ~jbuild:jbuild_syntax
~dune:dune_syntax ~dune:dune_syntax
@ -1582,7 +1608,7 @@ module Menhir = struct
~desc:"the menhir extension" ~desc:"the menhir extension"
[ (1, 0) ] [ (1, 0) ]
let t = let dparse =
record record
(let%map merge_into = field_o "merge_into" string (let%map merge_into = field_o "merge_into" string
and flags = field_oslu "flags" and flags = field_oslu "flags"
@ -1599,7 +1625,7 @@ module Menhir = struct
let () = let () =
Dune_project.Extension.register syntax Dune_project.Extension.register syntax
(return [ "menhir", t >>| fun x -> [T x] ]) (return [ "menhir", dparse >>| fun x -> [T x] ])
(* Syntax for jbuild files *) (* Syntax for jbuild files *)
let jbuild_syntax = let jbuild_syntax =
@ -1634,15 +1660,15 @@ module Alias_conf = struct
else else
s) s)
let t = let dparse =
record record
(let%map name = field "name" alias_name (let%map name = field "name" alias_name
and loc = loc and loc = loc
and package = field_o "package" Pkg.t and package = field_o "package" Pkg.dparse
and action = field_o "action" (located Action.Unexpanded.t) and action = field_o "action" (located Action.Unexpanded.dparse)
and locks = field "locks" (list String_with_vars.t) ~default:[] and locks = field "locks" (list String_with_vars.dparse) ~default:[]
and deps = field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty and deps = field "deps" (Bindings.dparse Dep_conf.dparse) ~default:Bindings.empty
and enabled_if = field_o "enabled_if" Blang.t and enabled_if = field_o "enabled_if" Blang.dparse
in in
{ name { name
; deps ; deps
@ -1665,15 +1691,16 @@ module Tests = struct
let gen_parse names = let gen_parse names =
record record
(let%map buildable = Buildable.t (let%map buildable = Buildable.dparse
and link_flags = field_oslu "link_flags" and link_flags = field_oslu "link_flags"
and names = names and names = names
and package = field_o "package" Pkg.t and package = field_o "package" Pkg.dparse
and locks = field "locks" (list String_with_vars.t) ~default:[] and locks = field "locks" (list String_with_vars.dparse) ~default:[]
and modes = field "modes" Executables.Link_mode.Set.t and modes = field "modes" Executables.Link_mode.Set.dparse
~default:Executables.Link_mode.Set.default ~default:Executables.Link_mode.Set.default
and deps = field "deps" (Bindings.t Dep_conf.t) ~default:Bindings.empty and deps =
and enabled_if = field_o "enabled_if" Blang.t field "deps" (Bindings.dparse Dep_conf.dparse) ~default:Bindings.empty
and enabled_if = field_o "enabled_if" Blang.dparse
in in
{ exes = { exes =
{ Executables. { Executables.
@ -1699,7 +1726,7 @@ module Copy_files = struct
; glob : String_with_vars.t ; glob : String_with_vars.t
} }
let t = String_with_vars.t let dparse = String_with_vars.dparse
end end
module Documentation = struct module Documentation = struct
@ -1709,7 +1736,7 @@ module Documentation = struct
; mld_files : Ordered_set_lang.t ; mld_files : Ordered_set_lang.t
} }
let t = let dparse =
record record
(let%map package = Pkg.field "documentation" (let%map package = Pkg.field "documentation"
and mld_files = Ordered_set_lang.field "mld_files" and mld_files = Ordered_set_lang.field "mld_files"
@ -1724,7 +1751,7 @@ end
module Include_subdirs = struct module Include_subdirs = struct
type t = No | Unqualified type t = No | Unqualified
let t = let dparse =
enum enum
[ "no", No [ "no", No
; "unqualified", Unqualified ; "unqualified", Unqualified
@ -1756,17 +1783,17 @@ module Stanzas = struct
type Stanza.t += Include of Loc.t * string type Stanza.t += Include of Loc.t * string
type constructors = (string * Stanza.t list Sexp.Of_sexp.t) list type constructors = (string * Stanza.t list Dsexp.Of_sexp.t) list
let stanzas : constructors = let stanzas : constructors =
[ "library", [ "library",
(let%map x = Library.t in (let%map x = Library.dparse in
[Library x]) [Library x])
; "executable" , Executables.single >>| execs ; "executable" , Executables.single >>| execs
; "executables", Executables.multi >>| execs ; "executables", Executables.multi >>| execs
; "rule", ; "rule",
(let%map loc = loc (let%map loc = loc
and x = Rule.t in and x = Rule.dparse in
[Rule { x with loc }]) [Rule { x with loc }])
; "ocamllex", ; "ocamllex",
(let%map loc = loc (let%map loc = loc
@ -1777,27 +1804,27 @@ module Stanzas = struct
and x = Rule.ocamlyacc in and x = Rule.ocamlyacc in
rules (Rule.ocamlyacc_to_rule loc x)) rules (Rule.ocamlyacc_to_rule loc x))
; "install", ; "install",
(let%map x = Install_conf.t in (let%map x = Install_conf.dparse in
[Install x]) [Install x])
; "alias", ; "alias",
(let%map x = Alias_conf.t in (let%map x = Alias_conf.dparse in
[Alias x]) [Alias x])
; "copy_files", ; "copy_files",
(let%map glob = Copy_files.t in (let%map glob = Copy_files.dparse in
[Copy_files {add_line_directive = false; glob}]) [Copy_files {add_line_directive = false; glob}])
; "copy_files#", ; "copy_files#",
(let%map glob = Copy_files.t in (let%map glob = Copy_files.dparse in
[Copy_files {add_line_directive = true; glob}]) [Copy_files {add_line_directive = true; glob}])
; "include", ; "include",
(let%map loc = loc (let%map loc = loc
and fn = relative_file in and fn = relative_file in
[Include (loc, fn)]) [Include (loc, fn)])
; "documentation", ; "documentation",
(let%map d = Documentation.t in (let%map d = Documentation.dparse in
[Documentation d]) [Documentation d])
; "jbuild_version", ; "jbuild_version",
(let%map () = Syntax.deleted_in Stanza.syntax (1, 0) (let%map () = Syntax.deleted_in Stanza.syntax (1, 0)
and _ = Jbuild_version.t in and _ = Jbuild_version.dparse in
[]) [])
; "tests", ; "tests",
(let%map () = Syntax.since Stanza.syntax (1, 0) (let%map () = Syntax.since Stanza.syntax (1, 0)
@ -1808,11 +1835,11 @@ module Stanzas = struct
and t = Tests.single in and t = Tests.single in
[Tests t]) [Tests t])
; "env", ; "env",
(let%map x = Dune_env.Stanza.t in (let%map x = Dune_env.Stanza.dparse in
[Dune_env.T x]) [Dune_env.T x])
; "include_subdirs", ; "include_subdirs",
(let%map () = Syntax.since Stanza.syntax (1, 1) (let%map () = Syntax.since Stanza.syntax (1, 1)
and t = Include_subdirs.t and t = Include_subdirs.dparse
and loc = loc in and loc = loc in
[Include_subdirs (loc, t)]) [Include_subdirs (loc, t)])
] ]
@ -1837,18 +1864,18 @@ module Stanzas = struct
exception Include_loop of Path.t * (Loc.t * Path.t) list exception Include_loop of Path.t * (Loc.t * Path.t) list
let rec parse stanza_parser ~lexer ~current_file ~include_stack sexps = let rec parse stanza_parser ~lexer ~current_file ~include_stack sexps =
List.concat_map sexps ~f:(Sexp.Of_sexp.parse stanza_parser Univ_map.empty) List.concat_map sexps ~f:(Dsexp.Of_sexp.parse stanza_parser Univ_map.empty)
|> List.concat_map ~f:(function |> List.concat_map ~f:(function
| Include (loc, fn) -> | Include (loc, fn) ->
let include_stack = (loc, current_file) :: include_stack in let include_stack = (loc, current_file) :: include_stack in
let dir = Path.parent_exn current_file in let dir = Path.parent_exn current_file in
let current_file = Path.relative dir fn in let current_file = Path.relative dir fn in
if not (Path.exists current_file) then if not (Path.exists current_file) then
Loc.fail loc "File %s doesn't exist." Errors.fail loc "File %s doesn't exist."
(Path.to_string_maybe_quoted current_file); (Path.to_string_maybe_quoted current_file);
if List.exists include_stack ~f:(fun (_, f) -> Path.equal f current_file) then if List.exists include_stack ~f:(fun (_, f) -> Path.equal f current_file) then
raise (Include_loop (current_file, include_stack)); raise (Include_loop (current_file, include_stack));
let sexps = Io.Sexp.load ~lexer current_file ~mode:Many in let sexps = Dsexp.Io.load ~lexer current_file ~mode:Many in
parse stanza_parser sexps ~lexer ~current_file ~include_stack parse stanza_parser sexps ~lexer ~current_file ~include_stack
| stanza -> [stanza]) | stanza -> [stanza])
@ -1856,8 +1883,8 @@ module Stanzas = struct
let (stanza_parser, lexer) = let (stanza_parser, lexer) =
let (parser, lexer) = let (parser, lexer) =
match (kind : File_tree.Dune_file.Kind.t) with match (kind : File_tree.Dune_file.Kind.t) with
| Jbuild -> (jbuild_parser, Usexp.Lexer.jbuild_token) | Jbuild -> (jbuild_parser, Dsexp.Lexer.jbuild_token)
| Dune -> (Dune_project.stanza_parser project, Usexp.Lexer.token) | Dune -> (Dune_project.stanza_parser project, Dsexp.Lexer.token)
in in
(Dune_project.set project parser, lexer) (Dune_project.set project parser, lexer)
in in
@ -1873,7 +1900,7 @@ module Stanzas = struct
(Path.to_string_maybe_quoted file) (Path.to_string_maybe_quoted file)
loc.Loc.start.pos_lnum loc.Loc.start.pos_lnum
in in
Loc.fail loc Errors.fail loc
"Recursive inclusion of jbuild files detected:\n\ "Recursive inclusion of jbuild files detected:\n\
File %s is included from %s%s" File %s is included from %s%s"
(Path.to_string_maybe_quoted file) (Path.to_string_maybe_quoted file)
@ -1889,6 +1916,6 @@ module Stanzas = struct
~f:(function Dune_env.T e -> Some e | _ -> None) ~f:(function Dune_env.T e -> Some e | _ -> None)
with with
| _ :: e :: _ -> | _ :: e :: _ ->
Loc.fail e.loc "The 'env' stanza cannot appear more than once" Errors.fail e.loc "The 'env' stanza cannot appear more than once"
| _ -> stanzas | _ -> stanzas
end end

View File

@ -1,5 +1,6 @@
(** Representation and parsing of jbuild files *) (** Representation and parsing of jbuild files *)
open! Stdune
open Import open Import
(** Ppx preprocessors *) (** Ppx preprocessors *)
@ -90,6 +91,8 @@ module Bindings : sig
type 'a t = 'a one list type 'a t = 'a one list
val map : 'a t -> f:('a -> 'b) -> 'b t
val find : 'a t -> string -> 'a list option val find : 'a t -> string -> 'a list option
val fold : 'a t -> f:('a one -> 'acc -> 'acc) -> init:'acc -> 'acc val fold : 'a t -> f:('a one -> 'acc -> 'acc) -> init:'acc -> 'acc
@ -100,7 +103,9 @@ module Bindings : sig
val singleton : 'a -> 'a t val singleton : 'a -> 'a t
val sexp_of_t : ('a -> Usexp.t) -> 'a t -> Usexp.t val dgen : 'a Dsexp.To_sexp.t -> 'a t Dsexp.To_sexp.t
val to_sexp : 'a Sexp.To_sexp.t -> 'a t Sexp.To_sexp.t
end end
module Dep_conf : sig module Dep_conf : sig
@ -113,8 +118,10 @@ module Dep_conf : sig
| Package of String_with_vars.t | Package of String_with_vars.t
| Universe | Universe
val t : t Sexp.Of_sexp.t val remove_locs : t -> t
val sexp_of_t : t -> Sexp.t
include Dsexp.Sexpable with type t := t
val to_sexp : t Sexp.To_sexp.t
end end
module Buildable : sig module Buildable : sig
@ -170,7 +177,7 @@ module Sub_system_info : sig
val syntax : Syntax.t val syntax : Syntax.t
(** Parse parameters written by the user in jbuid/dune files *) (** Parse parameters written by the user in jbuid/dune files *)
val parse : t Sexp.Of_sexp.t val parse : t Dsexp.Of_sexp.t
end end
module Register(M : S) : sig end module Register(M : S) : sig end
@ -184,13 +191,13 @@ module Mode_conf : sig
| Native | Native
| Best (** [Native] if available and [Byte] if not *) | Best (** [Native] if available and [Byte] if not *)
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
val compare : t -> t -> Ordering.t val compare : t -> t -> Ordering.t
val pp : Format.formatter -> t -> unit val pp : Format.formatter -> t -> unit
module Set : sig module Set : sig
include Set.S with type elt = t include Set.S with type elt = t
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
(** Both Byte and Native *) (** Both Byte and Native *)
val default : t val default : t
@ -260,8 +267,7 @@ module Executables : sig
; kind : Binary_kind.t ; kind : Binary_kind.t
} }
val t : t Sexp.Of_sexp.t include Dsexp.Sexpable with type t := t
val sexp_of_t : t Sexp.To_sexp.t
val exe : t val exe : t
val object_ : t val object_ : t
@ -391,6 +397,6 @@ module Stanzas : sig
: file:Path.t : file:Path.t
-> kind:File_tree.Dune_file.Kind.t -> kind:File_tree.Dune_file.Kind.t
-> Dune_project.t -> Dune_project.t
-> Sexp.Ast.t list -> Dsexp.Ast.t list
-> t -> t
end end

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
let parse_file path_opt = let parse_file path_opt =
@ -13,20 +14,20 @@ let parse_file path_opt =
let contents = String.concat ~sep:"\n" lines in let contents = String.concat ~sep:"\n" lines in
("<stdin>", contents) ("<stdin>", contents)
in in
Sexp.parse_string Dsexp.parse_string
~fname ~fname
~mode:Usexp.Parser.Mode.Many ~mode:Dsexp.Parser.Mode.Many
contents contents
let can_be_displayed_inline = let can_be_displayed_inline =
List.for_all ~f:(function List.for_all ~f:(function
| Usexp.Atom _ | Dsexp.Atom _
| Usexp.Quoted_string _ | Dsexp.Quoted_string _
| Usexp.Template _ | Dsexp.Template _
| Usexp.List [_] | Dsexp.List [_]
-> ->
true true
| Usexp.List _ | Dsexp.List _
-> ->
false false
) )
@ -42,21 +43,21 @@ let print_inline_list fmt indent sexps =
first := false first := false
else else
Format.pp_print_string fmt " "; Format.pp_print_string fmt " ";
Usexp.pp Usexp.Dune fmt sexp Dsexp.pp Dsexp.Dune fmt sexp
); );
Format.pp_print_string fmt ")" Format.pp_print_string fmt ")"
let rec pp_sexp indent fmt = let rec pp_sexp indent fmt =
function function
( Usexp.Atom _ ( Dsexp.Atom _
| Usexp.Quoted_string _ | Dsexp.Quoted_string _
| Usexp.Template _ | Dsexp.Template _
) as sexp ) as sexp
-> ->
Format.fprintf fmt "%a%a" Format.fprintf fmt "%a%a"
pp_indent indent pp_indent indent
(Usexp.pp Usexp.Dune) sexp (Dsexp.pp Dsexp.Dune) sexp
| Usexp.List sexps | Dsexp.List sexps
-> ->
if can_be_displayed_inline sexps then if can_be_displayed_inline sexps then
print_inline_list fmt indent sexps print_inline_list fmt indent sexps
@ -96,7 +97,7 @@ let pp_top_sexps fmt sexps =
first := false first := false
else else
Format.pp_print_string fmt "\n"; Format.pp_print_string fmt "\n";
pp_top_sexp fmt (Sexp.Ast.remove_locs sexp); pp_top_sexp fmt (Dsexp.Ast.remove_locs sexp);
) )
let with_output path_opt k = let with_output path_opt k =
@ -110,10 +111,10 @@ let with_output path_opt k =
let format_file ~input ~output = let format_file ~input ~output =
match parse_file input with match parse_file input with
| exception Usexp.Parse_error e -> | exception Dsexp.Parse_error e ->
Printf.printf Printf.printf
"Parse error: %s\n" "Parse error: %s\n"
(Usexp.Parse_error.message e) (Dsexp.Parse_error.message e)
| sexps -> | sexps ->
with_output output (fun fmt -> with_output output (fun fmt ->
pp_top_sexps fmt sexps; pp_top_sexps fmt sexps;

View File

@ -1,3 +1,5 @@
open! Stdune
(** Returns [true] if the input starts with "(* -*- tuareg -*- *)" *) (** Returns [true] if the input starts with "(* -*- tuareg -*- *)" *)
val is_script : Lexing.lexbuf -> bool val is_script : Lexing.lexbuf -> bool

View File

@ -1,4 +1,5 @@
{ {
open! Stdune
type first_line = type first_line =
{ lang : Loc.t * string { lang : Loc.t * string
; version : Loc.t * string ; version : Loc.t * string
@ -11,7 +12,7 @@ let make_loc lexbuf : Loc.t =
let invalid_lang_line start lexbuf = let invalid_lang_line start lexbuf =
lexbuf.Lexing.lex_start_p <- start; lexbuf.Lexing.lex_start_p <- start;
Loc.fail_lex lexbuf Errors.fail_lex lexbuf
"Invalid first line, expected: (lang <lang> <version>)" "Invalid first line, expected: (lang <lang> <version>)"
} }

View File

@ -1,13 +1,14 @@
open! Stdune
open Import open Import
open Sexp.Of_sexp open Dsexp.Of_sexp
module Kind = struct module Kind = struct
type t = type t =
| Dune | Dune
| Jbuilder | Jbuilder
let sexp_of_t t = let to_sexp t =
Sexp.atom_or_quoted_string Sexp.Atom
(match t with (match t with
| Dune -> "dune" | Dune -> "dune"
| Jbuilder -> "jbuilder") | Jbuilder -> "jbuilder")
@ -22,8 +23,8 @@ module Name : sig
val to_string_hum : t -> string val to_string_hum : t -> string
val named_of_sexp : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
val sexp_of_t : t Sexp.To_sexp.t val to_sexp : t Sexp.To_sexp.t
val encode : t -> string val encode : t -> string
val decode : string -> t val decode : string -> t
@ -58,11 +59,11 @@ end = struct
| Named s -> s | Named s -> s
| Anonymous p -> sprintf "<anonymous %s>" (Path.to_string_maybe_quoted p) | Anonymous p -> sprintf "<anonymous %s>" (Path.to_string_maybe_quoted p)
let sexp_of_t = function let to_sexp = function
| Named s -> Sexp.To_sexp.string s | Named s -> Sexp.To_sexp.string s
| Anonymous p -> | Anonymous p ->
List [ Sexp.unsafe_atom_of_string "anonymous" List [ Atom "anonymous"
; Path.sexp_of_t p ; Path.to_sexp p
] ]
let validate name = let validate name =
@ -84,12 +85,12 @@ end = struct
else else
None None
let named_of_sexp = let dparse =
Sexp.Of_sexp.plain_string (fun ~loc s -> Dsexp.Of_sexp.plain_string (fun ~loc s ->
if validate s then if validate s then
Named s Named s
else else
Sexp.Of_sexp.of_sexp_errorf loc "invalid project name") Dsexp.Of_sexp.of_sexp_errorf loc "invalid project name")
let encode = function let encode = function
| Named s -> s | Named s -> s
@ -131,10 +132,10 @@ module Project_file = struct
; mutable exists : bool ; mutable exists : bool
} }
let sexp_of_t { file; exists } = let to_sexp { file; exists } =
Sexp.To_sexp.( Sexp.To_sexp.(
record record
[ "file", Path.sexp_of_t file [ "file", Path.to_sexp file
; "exists", bool exists ; "exists", bool exists
]) ])
end end
@ -145,7 +146,7 @@ type t =
; root : Path.Local.t ; root : Path.Local.t
; version : string option ; version : string option
; packages : Package.t Package.Name.Map.t ; packages : Package.t Package.Name.Map.t
; stanza_parser : Stanza.t list Sexp.Of_sexp.t ; stanza_parser : Stanza.t list Dsexp.Of_sexp.t
; project_file : Project_file.t ; project_file : Project_file.t
} }
@ -202,14 +203,14 @@ let append_to_project_file t str =
module Extension = struct module Extension = struct
type t = type t =
{ syntax : Syntax.t { syntax : Syntax.t
; stanzas : Stanza.Parser.t list Sexp.Of_sexp.t ; stanzas : Stanza.Parser.t list Dsexp.Of_sexp.t
} }
type instance = type instance =
{ extension : t { extension : t
; version : Syntax.Version.t ; version : Syntax.Version.t
; loc : Loc.t ; loc : Loc.t
; parse_args : Stanza.Parser.t list Sexp.Of_sexp.t -> Stanza.Parser.t list ; parse_args : Stanza.Parser.t list Dsexp.Of_sexp.t -> Stanza.Parser.t list
} }
let extensions = Hashtbl.create 32 let extensions = Hashtbl.create 32
@ -224,7 +225,7 @@ module Extension = struct
let instantiate ~loc ~parse_args (name_loc, name) (ver_loc, ver) = let instantiate ~loc ~parse_args (name_loc, name) (ver_loc, ver) =
match Hashtbl.find extensions name with match Hashtbl.find extensions name with
| None -> | None ->
Loc.fail name_loc "Unknown extension %S.%s" name Errors.fail name_loc "Unknown extension %S.%s" name
(hint name (Hashtbl.keys extensions)) (hint name (Hashtbl.keys extensions))
| Some t -> | Some t ->
Syntax.check_supported t.syntax (ver_loc, ver); Syntax.check_supported t.syntax (ver_loc, ver);
@ -242,7 +243,7 @@ module Extension = struct
if f name then if f name then
let version = Syntax.greatest_supported_version ext.syntax in let version = Syntax.greatest_supported_version ext.syntax in
let parse_args p = let parse_args p =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
let dune_project_edited = ref false in let dune_project_edited = ref false in
parse (enter p) Univ_map.empty (List (Loc.of_pos __POS__, [])) parse (enter p) Univ_map.empty (List (Loc.of_pos __POS__, []))
|> List.map ~f:(fun (name, p) -> |> List.map ~f:(fun (name, p) ->
@ -251,10 +252,10 @@ module Extension = struct
if not !dune_project_edited then begin if not !dune_project_edited then begin
dune_project_edited := true; dune_project_edited := true;
Project_file_edit.append project_file Project_file_edit.append project_file
(Sexp.to_string ~syntax:Dune (Dsexp.to_string ~syntax:Dune
(List [ Sexp.atom "using" (List [ Dsexp.atom "using"
; Sexp.atom name ; Dsexp.atom name
; Sexp.atom (Syntax.Version.to_string version) ; Dsexp.atom (Syntax.Version.to_string version)
])) ]))
end; end;
p)) p))
@ -279,16 +280,16 @@ let key =
(fun { name; root; version; project_file; kind (fun { name; root; version; project_file; kind
; stanza_parser = _; packages = _ } -> ; stanza_parser = _; packages = _ } ->
Sexp.To_sexp.record Sexp.To_sexp.record
[ "name", Name.sexp_of_t name [ "name", Name.to_sexp name
; "root", Path.Local.sexp_of_t root ; "root", Path.Local.to_sexp root
; "version", Sexp.To_sexp.(option string) version ; "version", Sexp.To_sexp.(option string) version
; "project_file", Project_file.sexp_of_t project_file ; "project_file", Project_file.to_sexp project_file
; "kind", Kind.sexp_of_t kind ; "kind", Kind.to_sexp kind
]) ])
let set t = Sexp.Of_sexp.set key t let set t = Dsexp.Of_sexp.set key t
let get_exn () = let get_exn () =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
get key >>| function get key >>| function
| Some t -> t | Some t -> t
| None -> | None ->
@ -310,7 +311,7 @@ let anonymous = lazy (
; root = get_local_path Path.root ; root = get_local_path Path.root
; version = None ; version = None
; stanza_parser = ; stanza_parser =
Sexp.Of_sexp.(set_many parsing_context (sum lang.data)) Dsexp.Of_sexp.(set_many parsing_context (sum lang.data))
; project_file = { file = Path.relative Path.root filename; exists = false } ; project_file = { file = Path.relative Path.root filename; exists = false }
}) })
@ -330,12 +331,12 @@ let default_name ~dir ~packages =
match Name.named name with match Name.named name with
| Some x -> x | Some x -> x
| None -> | None ->
Loc.fail (Loc.in_file (Path.to_string (Package.opam_file pkg))) Errors.fail (Loc.in_file (Path.to_string (Package.opam_file pkg)))
"%S is not a valid opam package name." "%S is not a valid opam package name."
name name
let name_field ~dir ~packages = let name_field ~dir ~packages =
let%map name = field_o "name" Name.named_of_sexp in let%map name = field_o "name" Name.dparse in
match name with match name with
| Some x -> x | Some x -> x
| None -> default_name ~dir ~packages | None -> default_name ~dir ~packages
@ -348,7 +349,7 @@ let parse ~dir ~lang ~packages ~file =
multi_field "using" multi_field "using"
(let%map loc = loc (let%map loc = loc
and name = located string and name = located string
and ver = located Syntax.Version.t and ver = located Syntax.Version.dparse
and parse_args = capture and parse_args = capture
in in
(* We don't parse the arguments quite yet as we want to set (* We don't parse the arguments quite yet as we want to set
@ -361,7 +362,7 @@ let parse ~dir ~lang ~packages ~file =
(Syntax.name e.extension.syntax, e.loc))) (Syntax.name e.extension.syntax, e.loc)))
with with
| Error (name, _, loc) -> | Error (name, _, loc) ->
Loc.fail loc "Extension %S specified for the second time." name Errors.fail loc "Extension %S specified for the second time." name
| Ok map -> | Ok map ->
let project_file : Project_file.t = { file; exists = true } in let project_file : Project_file.t = { file; exists = true } in
let extensions = let extensions =
@ -375,14 +376,14 @@ let parse ~dir ~lang ~packages ~file =
(lang.data :: (lang.data ::
List.map extensions ~f:(fun (ext : Extension.instance) -> List.map extensions ~f:(fun (ext : Extension.instance) ->
ext.parse_args ext.parse_args
(Sexp.Of_sexp.set_many parsing_context ext.extension.stanzas))) (Dsexp.Of_sexp.set_many parsing_context ext.extension.stanzas)))
in in
{ kind = Dune { kind = Dune
; name ; name
; root = get_local_path dir ; root = get_local_path dir
; version ; version
; packages ; packages
; stanza_parser = Sexp.Of_sexp.(set_many parsing_context (sum stanzas)) ; stanza_parser = Dsexp.Of_sexp.(set_many parsing_context (sum stanzas))
; project_file ; project_file
}) })
@ -399,7 +400,7 @@ let make_jbuilder_project ~dir packages =
; version = None ; version = None
; packages ; packages
; stanza_parser = ; stanza_parser =
Sexp.Of_sexp.(set_many parsing_context (sum lang.data)) Dsexp.Of_sexp.(set_many parsing_context (sum lang.data))
; project_file = { file = Path.relative dir filename; exists = false } ; project_file = { file = Path.relative dir filename; exists = false }
} }

View File

@ -1,3 +1,4 @@
open! Stdune
(** dune-project files *) (** dune-project files *)
open Import open Import
@ -22,7 +23,7 @@ module Name : sig
(** Convert to a string that is suitable for human readable messages *) (** Convert to a string that is suitable for human readable messages *)
val to_string_hum : t -> string val to_string_hum : t -> string
val sexp_of_t : t -> Sexp.t val to_sexp : t Sexp.To_sexp.t
(** Convert to/from an encoded string that is suitable to use in filenames *) (** Convert to/from an encoded string that is suitable to use in filenames *)
val encode : t -> string val encode : t -> string
@ -41,7 +42,7 @@ val packages : t -> Package.t Package.Name.Map.t
val version : t -> string option val version : t -> string option
val name : t -> Name.t val name : t -> Name.t
val root : t -> Path.Local.t val root : t -> Path.Local.t
val stanza_parser : t -> Stanza.t list Sexp.Of_sexp.t val stanza_parser : t -> Stanza.t list Dsexp.Of_sexp.t
module Lang : sig module Lang : sig
(** [register id stanzas_parser] register a new language. Users will (** [register id stanzas_parser] register a new language. Users will
@ -62,7 +63,7 @@ module Extension : sig
in their [dune-project] file. [parser] is used to describe in their [dune-project] file. [parser] is used to describe
what [<args>] might be. *) what [<args>] might be. *)
val register : Syntax.t -> Stanza.Parser.t list Sexp.Of_sexp.t -> unit val register : Syntax.t -> Stanza.Parser.t list Dsexp.Of_sexp.t -> unit
end end
(** Load a project description from the following directory. [files] (** Load a project description from the following directory. [files]
@ -86,5 +87,5 @@ val ensure_project_file_exists : t -> unit
val append_to_project_file : t -> string -> unit val append_to_project_file : t -> string -> unit
(** Set the project we are currently parsing dune files for *) (** Set the project we are currently parsing dune files for *)
val set : t -> ('a, 'k) Sexp.Of_sexp.parser -> ('a, 'k) Sexp.Of_sexp.parser val set : t -> ('a, 'k) Dsexp.Of_sexp.parser -> ('a, 'k) Dsexp.Of_sexp.parser
val get_exn : unit -> (t, 'k) Sexp.Of_sexp.parser val get_exn : unit -> (t, 'k) Dsexp.Of_sexp.parser

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module Var = struct module Var = struct
@ -62,7 +63,7 @@ let extend t ~vars =
let extend_env x y = let extend_env x y =
extend x ~vars:y.vars extend x ~vars:y.vars
let sexp_of_t t = let to_sexp t =
let open Sexp.To_sexp in let open Sexp.To_sexp in
(list (pair string string)) (Map.to_list t.vars) (list (pair string string)) (Map.to_list t.vars)

View File

@ -1,4 +1,4 @@
open Import open! Stdune
module Var : sig module Var : sig
type t = string type t = string
@ -28,6 +28,6 @@ val diff : t -> t -> t
val update : t -> var:string -> f:(string option -> string option) -> t val update : t -> var:string -> f:(string option -> string option) -> t
val sexp_of_t : t -> Sexp.t val to_sexp : t -> Sexp.t
val of_string_map : string String.Map.t -> t val of_string_map : string String.Map.t -> t

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
exception Already_reported exception Already_reported
@ -15,3 +15,84 @@ let kerrf fmt ~f =
let die fmt = let die fmt =
kerrf fmt ~f:(fun s -> raise (Exn.Fatal_error s)) kerrf fmt ~f:(fun s -> raise (Exn.Fatal_error s))
let exnf t fmt =
Format.pp_open_box err_ppf 0;
Format.pp_print_as err_ppf 7 ""; (* "Error: " *)
kerrf (fmt^^ "@]") ~f:(fun s -> Exn.Loc_error (t, s))
let fail t fmt =
Format.pp_print_as err_ppf 7 ""; (* "Error: " *)
kerrf fmt ~f:(fun s ->
raise (Exn.Loc_error (t, s)))
let fail_lex lb fmt =
fail (Loc.of_lexbuf lb) fmt
let fail_opt t fmt =
match t with
| None -> die fmt
| Some t -> fail t fmt
let file_line path n =
Io.with_file_in ~binary:false path
~f:(fun ic ->
for _ = 1 to n - 1 do
ignore (input_line ic)
done;
input_line ic
)
let file_lines path ~start ~stop =
Io.with_file_in ~binary:true path
~f:(fun ic ->
let rec aux acc lnum =
if lnum > stop then
List.rev acc
else if lnum < start then
(ignore (input_line ic);
aux acc (lnum + 1))
else
let line = input_line ic in
aux ((string_of_int lnum, line) :: acc) (lnum + 1)
in
aux [] 1
)
let print ppf loc =
let { Loc.start; stop } = loc in
let start_c = start.pos_cnum - start.pos_bol in
let stop_c = stop.pos_cnum - start.pos_bol in
let num_lines = stop.pos_lnum - start.pos_lnum in
let pp_file_excerpt pp () =
let whole_file = start_c = 0 && stop_c = 0 in
if not whole_file then
let path = Path.of_string start.pos_fname in
if Path.exists path then
let line = file_line path start.pos_lnum in
if stop_c <= String.length line then
let len = stop_c - start_c in
Format.fprintf pp "%s\n%*s\n" line
stop_c
(String.make len '^')
else if num_lines <= 10 then
let lines = file_lines path ~start:start.pos_lnum ~stop:stop.pos_lnum in
let last_lnum = Option.map ~f:fst (List.last lines) in
let padding_width = Option.value_exn
(Option.map ~f:String.length last_lnum) in
List.iter ~f:(fun (lnum, l) ->
Format.fprintf pp "%*s: %s\n" padding_width lnum l)
lines
in
Format.fprintf ppf
"@{<loc>File \"%s\", line %d, characters %d-%d:@}@\n%a"
start.pos_fname start.pos_lnum start_c stop_c
pp_file_excerpt ()
(* This is ugly *)
let printer = ref (Printf.eprintf "%s%!")
let print_to_console s = !printer s
let warn t fmt =
kerrf ~f:print_to_console
("%a@{<warning>Warning@}: " ^^ fmt ^^ "@.") print t

View File

@ -1,3 +1,4 @@
open Stdune
(** Dealing with errors *) (** Dealing with errors *)
(* CR-soon diml: stop including this in [Import] *) (* CR-soon diml: stop including this in [Import] *)
@ -21,3 +22,18 @@ val kerrf
: ('a, Format.formatter, unit, 'b) format4 : ('a, Format.formatter, unit, 'b) format4
-> f:(string -> 'b) -> f:(string -> 'b)
-> 'a -> 'a
val exnf : Loc.t -> ('a, Format.formatter, unit, exn) format4 -> 'a
val fail : Loc.t -> ('a, Format.formatter, unit, 'b ) format4 -> 'a
val fail_lex : Lexing.lexbuf -> ('a, Format.formatter, unit, 'b ) format4 -> 'a
val fail_opt : Loc.t option -> ('a, Format.formatter, unit, 'b ) format4 -> 'a
(** Prints "File ..., line ..., characters ...:\n" *)
val print : Format.formatter -> Loc.t -> unit
(** Prints a warning *)
val warn : Loc.t -> ('a, Format.formatter, unit) format -> 'a
val print_to_console : string -> unit
val printer : (string -> unit) ref

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Build.O open Build.O

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
module Execution_context : sig module Execution_context : sig
type t type t
@ -234,7 +234,7 @@ module Var = struct
fiber ctx k fiber ctx k
let create () = let create () =
create ~name:"var" (fun _ -> Sexp.atom_or_quoted_string "var") create ~name:"var" (fun _ -> Sexp.To_sexp.string "var")
end end
let with_error_handler f ~on_error ctx k = let with_error_handler f ~on_error ctx k =

View File

@ -1,6 +1,6 @@
(** Concurrency library *) (** Concurrency library *)
open Stdune open! Stdune
(** {1 Generals} *) (** {1 Generals} *)

View File

@ -1,8 +1,9 @@
open! Stdune
open! Import open! Import
module Dune_file = struct module Dune_file = struct
module Kind = struct module Kind = struct
type t = Usexp.syntax = Jbuild | Dune type t = Dsexp.syntax = Jbuild | Dune
let of_basename = function let of_basename = function
| "dune" -> Dune | "dune" -> Dune
@ -10,14 +11,14 @@ module Dune_file = struct
| _ -> assert false | _ -> assert false
let lexer = function let lexer = function
| Dune -> Sexp.Lexer.token | Dune -> Dsexp.Lexer.token
| Jbuild -> Sexp.Lexer.jbuild_token | Jbuild -> Dsexp.Lexer.jbuild_token
end end
module Plain = struct module Plain = struct
type t = type t =
{ path : Path.t { path : Path.t
; mutable sexps : Sexp.Ast.t list ; mutable sexps : Dsexp.Ast.t list
} }
end end
@ -39,7 +40,7 @@ module Dune_file = struct
let extract_ignored_subdirs = let extract_ignored_subdirs =
let stanza = let stanza =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
let sub_dir = let sub_dir =
plain_string (fun ~loc dn -> plain_string (fun ~loc dn ->
if Filename.dirname dn <> Filename.current_dir_name || if Filename.dirname dn <> Filename.current_dir_name ||
@ -58,9 +59,9 @@ module Dune_file = struct
fun sexps -> fun sexps ->
let ignored_subdirs, sexps = let ignored_subdirs, sexps =
List.partition_map sexps ~f:(fun sexp -> List.partition_map sexps ~f:(fun sexp ->
match (sexp : Sexp.Ast.t) with match (sexp : Dsexp.Ast.t) with
| List (_, (Atom (_, A "ignored_subdirs") :: _)) -> | List (_, (Atom (_, A "ignored_subdirs") :: _)) ->
Left (Sexp.Of_sexp.parse stanza Univ_map.empty sexp) Left (Dsexp.Of_sexp.parse stanza Univ_map.empty sexp)
| _ -> Right sexp) | _ -> Right sexp)
in in
let ignored_subdirs = let ignored_subdirs =
@ -75,7 +76,7 @@ module Dune_file = struct
(Contents.Ocaml_script file, String.Set.empty) (Contents.Ocaml_script file, String.Set.empty)
else else
let sexps = let sexps =
Usexp.Parser.parse lb ~lexer:(Kind.lexer kind) ~mode:Many Dsexp.Parser.parse lb ~lexer:(Kind.lexer kind) ~mode:Many
in in
let ignored_subdirs, sexps = extract_ignored_subdirs sexps in let ignored_subdirs, sexps = extract_ignored_subdirs sexps in
(Plain { path = file; sexps }, ignored_subdirs) (Plain { path = file; sexps }, ignored_subdirs)
@ -88,11 +89,12 @@ let load_jbuild_ignore path =
if Filename.dirname fn = Filename.current_dir_name then if Filename.dirname fn = Filename.current_dir_name then
true true
else begin else begin
Loc.(warn (of_pos ( Path.to_string path Errors.(warn (Loc.of_pos
, i + 1, 0 ( Path.to_string path
, String.length fn , i + 1, 0
)) , String.length fn
"subdirectory expression %s ignored" fn); ))
"subdirectory expression %s ignored" fn);
false false
end) end)
|> String.Set.of_list |> String.Set.of_list

View File

@ -1,12 +1,13 @@
open! Stdune
(** Dune representation of the source tree *) (** Dune representation of the source tree *)
open! Import open! Import
module Dune_file : sig module Dune_file : sig
module Kind : sig module Kind : sig
type t = Usexp.syntax = Jbuild | Dune type t = Dsexp.syntax = Jbuild | Dune
val lexer : t -> Sexp.Lexer.t val lexer : t -> Dsexp.Lexer.t
end end
module Plain : sig module Plain : sig
@ -15,7 +16,7 @@ module Dune_file : sig
as we don't need them. *) as we don't need them. *)
type t = type t =
{ path : Path.t { path : Path.t
; mutable sexps : Sexp.Ast.t list ; mutable sexps : Dsexp.Ast.t list
} }
end end

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module P = Variant module P = Variant

View File

@ -1,5 +1,6 @@
(** Findlib database *) (** Findlib database *)
open! Stdune
open Import open Import
(** Findlib database *) (** Findlib database *)

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Meta open Meta

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module Menhir_rules = Menhir module Menhir_rules = Menhir
open Dune_file open Dune_file
@ -61,11 +62,11 @@ module Gen(P : Install_rules.Params) = struct
match Module.Name.Map.find modules mod_name with match Module.Name.Map.find modules mod_name with
| Some m -> | Some m ->
if not (Module.has_impl m) then if not (Module.has_impl m) then
Loc.fail loc "Module %a has no implementation." Errors.fail loc "Module %a has no implementation."
Module.Name.pp mod_name Module.Name.pp mod_name
else else
{ Exe.Program.name; main_module_name = mod_name } { Exe.Program.name; main_module_name = mod_name }
| None -> Loc.fail loc "Module %a doesn't exist." | None -> Errors.fail loc "Module %a doesn't exist."
Module.Name.pp mod_name) Module.Name.pp mod_name)
in in
@ -295,7 +296,7 @@ module Gen(P : Install_rules.Params) = struct
SC.add_rule sctx SC.add_rule sctx
(Build.fail ~targets (Build.fail ~targets
{ fail = fun () -> { fail = fun () ->
Loc.fail m.loc Errors.fail m.loc
"I can't determine what library/executable the files \ "I can't determine what library/executable the files \
produced by this stanza are part of." produced by this stanza are part of."
}) })

View File

@ -1,3 +1,4 @@
open! Stdune
open! Import open! Import
(* Generate rules. Returns evaluated jbuilds per context names. *) (* Generate rules. Returns evaluated jbuilds per context names. *)

View File

@ -1,3 +1,3 @@
open Import open Stdune
val parse_string : string -> (Re.t, int * string) result val parse_string : string -> (Re.t, int * string) Result.result

View File

@ -1,4 +1,5 @@
{ {
open! Stdune
open Re open Re
let no_slash = diff any (char '/') let no_slash = diff any (char '/')
@ -59,8 +60,8 @@ and char_set st = parse
let parse_string s = let parse_string s =
let lb = Lexing.from_string s in let lb = Lexing.from_string s in
match initial lb with match initial lb with
| re -> Import.Ok re | re -> Result.Ok re
| exception Failure msg -> | exception Failure msg ->
Import.Error (Lexing.lexeme_start lb, msg) Error (Lexing.lexeme_start lb, msg)
} }

View File

@ -1,3 +1,5 @@
open! Stdune
include Stdune include Stdune
include Errors include Errors
@ -87,6 +89,4 @@ module No_io = struct
module Io = struct end module Io = struct end
end end
(* This is ugly *) let print_to_console = Errors.print_to_console
let printer = ref (Printf.eprintf "%s%!")
let print_to_console s = !printer s

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Dune_file open Dune_file
open Build.O open Build.O
@ -37,7 +38,7 @@ module Backend = struct
(let%map loc = loc (let%map loc = loc
and runner_libraries = field "runner_libraries" (list (located string)) ~default:[] and runner_libraries = field "runner_libraries" (list (located string)) ~default:[]
and flags = Ordered_set_lang.Unexpanded.field "flags" and flags = Ordered_set_lang.Unexpanded.field "flags"
and generate_runner = field_o "generate_runner" (located Action.Unexpanded.t) and generate_runner = field_o "generate_runner" (located Action.Unexpanded.dparse)
and extends = field "extends" (list (located string)) ~default:[] and extends = field "extends" (list (located string)) ~default:[]
in in
{ loc { loc
@ -74,21 +75,21 @@ module Backend = struct
resolve x >>= fun lib -> resolve x >>= fun lib ->
match get ~loc lib with match get ~loc lib with
| None -> | None ->
Error (Loc.exnf loc "%S is not an %s" name Error (Errors.exnf loc "%S is not an %s" name
(desc ~plural:false)) (desc ~plural:false))
| Some t -> Ok t)) | Some t -> Ok t))
} }
let to_sexp t = let dgen t =
let open Sexp.To_sexp in let open Dsexp.To_sexp in
let lib x = string (Lib.name x) in let lib x = string (Lib.name x) in
let f x = string (Lib.name x.lib) in let f x = string (Lib.name x.lib) in
((1, 0), ((1, 0),
record_fields record_fields
[ field "runner_libraries" (list lib) [ field "runner_libraries" (list lib)
(Result.ok_exn t.runner_libraries) (Result.ok_exn t.runner_libraries)
; field "flags" Ordered_set_lang.Unexpanded.sexp_of_t t.info.flags ; field "flags" Ordered_set_lang.Unexpanded.dgen t.info.flags
; field_o "generate_runner" Action.Unexpanded.sexp_of_t ; field_o "generate_runner" Action.Unexpanded.dgen
(Option.map t.info.generate_runner ~f:snd) (Option.map t.info.generate_runner ~f:snd)
; field "extends" (list f) (Result.ok_exn t.extends) ~default:[] ; field "extends" (list f) (Result.ok_exn t.extends) ~default:[]
]) ])
@ -135,7 +136,7 @@ include Sub_system.Register_end_point(
~else_: ~else_:
(record (record
(let%map loc = loc (let%map loc = loc
and deps = field "deps" (list Dep_conf.t) ~default:[] and deps = field "deps" (list Dep_conf.dparse) ~default:[]
and flags = Ordered_set_lang.Unexpanded.field "flags" and flags = Ordered_set_lang.Unexpanded.field "flags"
and backend = field_o "backend" (located string) and backend = field_o "backend" (located string)
and libraries = field "libraries" (list (located string)) ~default:[] and libraries = field "libraries" (list (located string)) ~default:[]
@ -260,9 +261,7 @@ include Sub_system.Register_end_point(
SC.add_alias_action sctx SC.add_alias_action sctx
~loc:(Some info.loc) ~loc:(Some info.loc)
(Build_system.Alias.runtest ~dir) (Build_system.Alias.runtest ~dir)
~stamp:(List [ Sexp.unsafe_atom_of_string "ppx-runner" ~stamp:("ppx-runner", name)
; Quoted_string name
])
(let module A = Action in (let module A = Action in
let exe = Path.relative inline_test_dir (name ^ ".exe") in let exe = Path.relative inline_test_dir (name ^ ".exe") in
Build.path exe >>> Build.path exe >>>

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
module Section = struct module Section = struct
@ -58,8 +59,8 @@ module Section = struct
|"misc" -> Some Misc |"misc" -> Some Misc
| _ -> None | _ -> None
let t = let dparse =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
enum enum
[ "lib" , Lib [ "lib" , Lib
; "lib_root" , Lib_root ; "lib_root" , Lib_root
@ -271,7 +272,7 @@ let load_install_file path =
; pos_cnum = col ; pos_cnum = col
} }
in in
Loc.fail { start = pos; stop = pos } fmt Errors.fail { start = pos; stop = pos } fmt
in in
List.concat_map file.file_contents ~f:(function List.concat_map file.file_contents ~f:(function
| Variable (pos, section, files) -> begin | Variable (pos, section, files) -> begin

View File

@ -1,6 +1,6 @@
(** Opam install file *) (** Opam install file *)
open Stdune open! Stdune
module Section : sig module Section : sig
type t = type t =
@ -19,7 +19,7 @@ module Section : sig
| Man | Man
| Misc | Misc
val t : t Sexp.Of_sexp.t val dparse : t Dsexp.Of_sexp.t
(** [true] iff the executable bit should be set for files installed (** [true] iff the executable bit should be set for files installed
in this location. *) in this location. *)

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Dune_file open Dune_file
open Build.O open Build.O
@ -22,7 +23,7 @@ module Gen(P : Params) = struct
(Build.arr (fun () -> (Build.arr (fun () ->
let dune_version = Option.value_exn (Lib.dune_version lib) in let dune_version = Option.value_exn (Lib.dune_version lib) in
Format.asprintf "%a@." Format.asprintf "%a@."
(Sexp.pp (Stanza.File_kind.of_syntax dune_version)) (Dsexp.pp (Stanza.File_kind.of_syntax dune_version))
(Lib.Sub_system.dump_config lib (Lib.Sub_system.dump_config lib
|> Installed_dune_file.gen ~dune_version)) |> Installed_dune_file.gen ~dune_version))
>>> Build.write_file_dyn >>> Build.write_file_dyn

View File

@ -1,9 +1,9 @@
open Import open! Stdune
let parse_sub_systems ~parsing_context sexps = let parse_sub_systems ~parsing_context sexps =
List.filter_map sexps ~f:(fun sexp -> List.filter_map sexps ~f:(fun sexp ->
let name, ver, data = let name, ver, data =
Sexp.Of_sexp.(parse (triple string (located Syntax.Version.t) raw) Dsexp.Of_sexp.(parse (triple string (located Syntax.Version.dparse) raw)
parsing_context) sexp parsing_context) sexp
in in
match Sub_system_name.get name with match Sub_system_name.get name with
@ -12,12 +12,12 @@ let parse_sub_systems ~parsing_context sexps =
correspond to plugins that are not in use in the current correspond to plugins that are not in use in the current
workspace. *) workspace. *)
None None
| Some name -> Some (name, (Sexp.Ast.loc sexp, ver, data))) | Some name -> Some (name, (Dsexp.Ast.loc sexp, ver, data)))
|> Sub_system_name.Map.of_list |> Sub_system_name.Map.of_list
|> (function |> (function
| Ok x -> x | Ok x -> x
| Error (name, _, (loc, _, _)) -> | Error (name, _, (loc, _, _)) ->
Loc.fail loc "%S present twice" (Sub_system_name.to_string name)) Errors.fail loc "%S present twice" (Sub_system_name.to_string name))
|> Sub_system_name.Map.mapi ~f:(fun name (_, version, data) -> |> Sub_system_name.Map.mapi ~f:(fun name (_, version, data) ->
let (module M) = Dune_file.Sub_system_info.get name in let (module M) = Dune_file.Sub_system_info.get name in
Syntax.check_supported M.syntax version; Syntax.check_supported M.syntax version;
@ -32,10 +32,10 @@ let parse_sub_systems ~parsing_context sexps =
| (_, _) -> | (_, _) ->
Univ_map.add parsing_context (Syntax.key M.syntax) (snd version) Univ_map.add parsing_context (Syntax.key M.syntax) (snd version)
in in
M.T (Sexp.Of_sexp.parse M.parse parsing_context data)) M.T (Dsexp.Of_sexp.parse M.parse parsing_context data))
let of_sexp = let of_sexp =
let open Sexp.Of_sexp in let open Dsexp.Of_sexp in
let version = let version =
plain_string (fun ~loc -> function plain_string (fun ~loc -> function
| "1" -> (0, 0) | "1" -> (0, 0)
@ -64,45 +64,45 @@ let load fname =
which point we can decide what lexer to use for the reset of which point we can decide what lexer to use for the reset of
the file. *) the file. *)
let state = ref 0 in let state = ref 0 in
let lexer = ref Sexp.Lexer.token in let lexer = ref Dsexp.Lexer.token in
let lexer lb = let lexer lb =
let token : Sexp.Lexer.Token.t = !lexer lb in let token : Dsexp.Lexer.Token.t = !lexer lb in
(match !state, token with (match !state, token with
| 0, Lparen -> state := 1 | 0, Lparen -> state := 1
| 1, Atom (A "dune") -> state := 2 | 1, Atom (A "dune") -> state := 2
| 2, Atom (A "1") -> state := 3; lexer := Sexp.Lexer.jbuild_token | 2, Atom (A "1") -> state := 3; lexer := Dsexp.Lexer.jbuild_token
| 2, Atom (A "2") -> state := 3; lexer := Sexp.Lexer.token | 2, Atom (A "2") -> state := 3; lexer := Dsexp.Lexer.token
| 2, Atom (A version) -> | 2, Atom (A version) ->
Loc.fail (Sexp.Loc.of_lexbuf lexbuf) "Unsupported version %S" version Errors.fail (Loc.of_lexbuf lexbuf) "Unsupported version %S" version
| 3, _ -> () | 3, _ -> ()
| _ -> | _ ->
Loc.fail (Sexp.Loc.of_lexbuf lexbuf) Errors.fail (Loc.of_lexbuf lexbuf)
"This <lib>.dune file looks invalid, it should \ "This <lib>.dune file looks invalid, it should \
contain a S-expression of the form (dune x.y ..)" contain a S-expression of the form (dune x.y ..)"
); );
token token
in in
Sexp.Of_sexp.parse of_sexp Univ_map.empty Dsexp.Of_sexp.parse of_sexp Univ_map.empty
(Sexp.Parser.parse ~lexer ~mode:Single lexbuf)) (Dsexp.Parser.parse ~lexer ~mode:Single lexbuf))
let gen ~(dune_version : Syntax.Version.t) confs = let gen ~(dune_version : Syntax.Version.t) confs =
let sexps = let sexps =
Sub_system_name.Map.to_list confs Sub_system_name.Map.to_list confs
|> List.map ~f:(fun (name, (ver, conf)) -> |> List.map ~f:(fun (name, (ver, conf)) ->
let (module M) = Dune_file.Sub_system_info.get name in let (module M) = Dune_file.Sub_system_info.get name in
Sexp.List [ Sexp.atom (Sub_system_name.to_string name) Dsexp.List [ Dsexp.atom (Sub_system_name.to_string name)
; Syntax.Version.sexp_of_t ver ; Syntax.Version.dgen ver
; conf ; conf
]) ])
in in
Sexp.List Dsexp.List
[ Sexp.unsafe_atom_of_string "dune" [ Dsexp.unsafe_atom_of_string "dune"
; Sexp.unsafe_atom_of_string ; Dsexp.unsafe_atom_of_string
(match dune_version with (match dune_version with
| (0, 0) -> "1" | (0, 0) -> "1"
| (x, _) when x >= 1 -> "2" | (x, _) when x >= 1 -> "2"
| (_, _) -> | (_, _) ->
Exn.code_error "Cannot generate dune with unknown version" Exn.code_error "Cannot generate dune with unknown version"
["dune_version", Syntax.Version.sexp_of_t dune_version]) ["dune_version", Syntax.Version.to_sexp dune_version])
; List sexps ; List sexps
] ]

View File

@ -1,9 +1,9 @@
(** Dune files that are installed on the system *) (** Dune files that are installed on the system *)
open Stdune open! Stdune
val load : Path.t -> Dune_file.Sub_system_info.t Sub_system_name.Map.t val load : Path.t -> Dune_file.Sub_system_info.t Sub_system_name.Map.t
val gen val gen
: dune_version:Syntax.Version.t : dune_version:Syntax.Version.t
-> (Syntax.Version.t * Sexp.t) Sub_system_name.Map.t -> (Syntax.Version.t * Dsexp.t) Sub_system_name.Map.t
-> Sexp.t -> Dsexp.t

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Dune_file open Dune_file
@ -73,7 +74,7 @@ module Jbuilds = struct
(match (kind : File_tree.Dune_file.Kind.t) with (match (kind : File_tree.Dune_file.Kind.t) with
| Jbuild -> () | Jbuild -> ()
| Dune -> | Dune ->
Loc.fail loc Errors.fail loc
"#require is no longer supported in dune files.\n\ "#require is no longer supported in dune files.\n\
You can use the following function instead of \ You can use the following function instead of \
Unix.open_process_in:\n\ Unix.open_process_in:\n\
@ -84,7 +85,7 @@ module Jbuilds = struct
| [] -> acc | [] -> acc
| ["unix"] -> Unix | ["unix"] -> Unix
| _ -> | _ ->
Loc.fail loc Errors.fail loc
"Using libraries other that \"unix\" is not supported.\n\ "Using libraries other that \"unix\" is not supported.\n\
See the manual for details."; See the manual for details.";
in in
@ -207,7 +208,7 @@ end
Did you forgot to call [Jbuild_plugin.V*.send]?" Did you forgot to call [Jbuild_plugin.V*.send]?"
(Path.to_string file); (Path.to_string file);
Fiber.return Fiber.return
(Io.Sexp.load generated_jbuild ~mode:Many (Dsexp.Io.load generated_jbuild ~mode:Many
~lexer:(File_tree.Dune_file.Kind.lexer kind) ~lexer:(File_tree.Dune_file.Kind.lexer kind)
|> Jbuild.parse ~dir ~file ~project ~kind ~ignore_promoted_rules)) |> Jbuild.parse ~dir ~file ~project ~kind ~ignore_promoted_rules))
>>| fun dynamic -> >>| fun dynamic ->

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
module Jbuild : sig module Jbuild : sig
type t = type t =

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open! No_io open! No_io
open Build.O open Build.O

View File

@ -1,5 +1,6 @@
(** Generate rules for js_of_ocaml *) (** Generate rules for js_of_ocaml *)
open! Stdune
open Import open Import
open Dune_file open Dune_file

View File

@ -1,4 +1,5 @@
open Import open Import
open! Stdune
open Result.O open Result.O
(* +-----------------------------------------------------------------+ (* +-----------------------------------------------------------------+
@ -202,7 +203,7 @@ module Sub_system0 = struct
module type S = sig module type S = sig
type t type t
type sub_system += T of t type sub_system += T of t
val to_sexp : (t -> Syntax.Version.t * Sexp.t) option val dgen : (t -> Syntax.Version.t * Dsexp.t) option
end end
type 'a s = (module S with type t = 'a) type 'a s = (module S with type t = 'a)
@ -319,7 +320,7 @@ exception Error of Error.t
let not_available ~loc reason fmt = let not_available ~loc reason fmt =
Errors.kerrf fmt ~f:(fun s -> Errors.kerrf fmt ~f:(fun s ->
Loc.fail loc "%s %a" s Errors.fail loc "%s %a" s
Error.Library_not_available.Reason.pp reason) Error.Library_not_available.Reason.pp reason)
(* +-----------------------------------------------------------------+ (* +-----------------------------------------------------------------+
@ -455,7 +456,7 @@ module Sub_system = struct
-> lib -> lib
-> Info.t -> Info.t
-> t -> t
val to_sexp : (t -> Syntax.Version.t * Sexp.t) option val dgen : (t -> Syntax.Version.t * Dsexp.t) option
end end
module type S' = sig module type S' = sig
@ -491,7 +492,7 @@ module Sub_system = struct
| M.Info.T info -> | M.Info.T info ->
let get ~loc lib' = let get ~loc lib' =
if lib.unique_id = lib'.unique_id then if lib.unique_id = lib'.unique_id then
Loc.fail loc "Library %S depends on itself" lib.name Errors.fail loc "Library %S depends on itself" lib.name
else else
M.get lib' M.get lib'
in in
@ -502,7 +503,7 @@ module Sub_system = struct
let dump_config lib = let dump_config lib =
Sub_system_name.Map.filter_map lib.sub_systems ~f:(fun (lazy inst) -> Sub_system_name.Map.filter_map lib.sub_systems ~f:(fun (lazy inst) ->
let (Sub_system0.Instance.T ((module M), t)) = inst in let (Sub_system0.Instance.T ((module M), t)) = inst in
Option.map ~f:(fun f -> f t) M.to_sexp) Option.map ~f:(fun f -> f t) M.dgen)
end end
(* +-----------------------------------------------------------------+ (* +-----------------------------------------------------------------+
@ -582,25 +583,25 @@ let check_private_deps lib ~loc ~allow_private_deps =
Ok lib Ok lib
let already_in_table (info : Info.t) name x = let already_in_table (info : Info.t) name x =
let to_sexp = Sexp.To_sexp.(pair Path.sexp_of_t string) in let dgen = Sexp.To_sexp.(pair Path.to_sexp string) in
let sexp = let sexp =
match x with match x with
| St_initializing x -> | St_initializing x ->
Sexp.List [Sexp.unsafe_atom_of_string "Initializing"; Sexp.List [Sexp.Atom "Initializing";
Path.sexp_of_t x.path] Path.to_sexp x.path]
| St_found t -> | St_found t ->
List [Sexp.unsafe_atom_of_string "Found"; List [Sexp.Atom "Found";
Path.sexp_of_t t.info.src_dir] Path.to_sexp t.info.src_dir]
| St_not_found -> | St_not_found ->
Sexp.unsafe_atom_of_string "Not_found" Sexp.Atom "Not_found"
| St_hidden (_, { path; reason; _ }) -> | St_hidden (_, { path; reason; _ }) ->
List [Sexp.unsafe_atom_of_string "Hidden"; List [Sexp.Atom "Hidden";
Path.sexp_of_t path; Sexp.atom reason] Path.to_sexp path; Sexp.Atom reason]
in in
Exn.code_error Exn.code_error
"Lib_db.DB: resolver returned name that's already in the table" "Lib_db.DB: resolver returned name that's already in the table"
[ "name" , Sexp.atom name [ "name" , Sexp.To_sexp.string name
; "returned_lib" , to_sexp (info.src_dir, name) ; "returned_lib" , dgen (info.src_dir, name)
; "conflicting_with", sexp ; "conflicting_with", sexp
] ]
@ -1137,7 +1138,7 @@ let report_lib_error ppf (e : Error.t) =
| No_solution_found_for_select { loc } -> | No_solution_found_for_select { loc } ->
Format.fprintf ppf Format.fprintf ppf
"%a@{<error>Error@}: No solution found for this select form.\n" "%a@{<error>Error@}: No solution found for this select form.\n"
Loc.print loc Errors.print loc
| Dependency_cycle cycle -> | Dependency_cycle cycle ->
Format.fprintf ppf Format.fprintf ppf
"@{<error>Error@}: Dependency cycle detected between the \ "@{<error>Error@}: Dependency cycle detected between the \

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
(** {1 Generals} *) (** {1 Generals} *)
@ -331,7 +332,7 @@ module Sub_system : sig
-> lib -> lib
-> Info.t -> Info.t
-> t -> t
val to_sexp : (t -> Syntax.Version.t * Sexp.t) option val dgen : (t -> Syntax.Version.t * Dsexp.t) option
end end
module Register(M : S) : sig module Register(M : S) : sig
@ -339,7 +340,7 @@ module Sub_system : sig
val get : lib -> M.t option val get : lib -> M.t option
end end
val dump_config : lib -> (Syntax.Version.t * Sexp.t) Sub_system_name.Map.t val dump_config : lib -> (Syntax.Version.t * Dsexp.t) Sub_system_name.Map.t
end with type lib := t end with type lib := t
(** {1 Dependencies for META files} *) (** {1 Dependencies for META files} *)

View File

@ -1,4 +1,4 @@
open Import open! Stdune
module Kind = struct module Kind = struct
type t = type t =

View File

@ -3,7 +3,7 @@
(** This module implements tracking of external library dependencies, (** This module implements tracking of external library dependencies,
for [dune external-lib-deps] *) for [dune external-lib-deps] *)
open Import open! Stdune
module Kind : sig module Kind : sig
type t = type t =

View File

@ -1,3 +1,4 @@
open! Stdune
open Import open Import
open Build.O open Build.O
open Dune_file open Dune_file
@ -226,7 +227,7 @@ module Gen (P : Install_rules.Params) = struct
if not (match Path.parent p with if not (match Path.parent p with
| None -> false | None -> false
| Some p -> Path.Set.mem all_dirs p) then | Some p -> Path.Set.mem all_dirs p) then
Loc.fail loc Errors.fail loc
"File %a is not part of the current directory group. \ "File %a is not part of the current directory group. \
This is not allowed." This is not allowed."
Path.pp (Path.drop_optional_build_context p) Path.pp (Path.drop_optional_build_context p)

View File

@ -1,4 +1,4 @@
open Stdune open! Stdune
open Dune_file open Dune_file
module Gen (S : sig val sctx : Super_context.t end) : sig module Gen (S : sig val sctx : Super_context.t end) : sig
@ -13,6 +13,6 @@ module Gen (S : sig val sctx : Super_context.t end) : sig
-> dir_contents:Dir_contents.t -> dir_contents:Dir_contents.t
-> dir:Path.t -> dir:Path.t
-> scope:Scope.t -> scope:Scope.t
-> dir_kind:Usexp.syntax -> dir_kind:Dsexp.syntax
-> Compilation_context.t * Merlin.t -> Compilation_context.t * Merlin.t
end end

View File

@ -1,146 +0,0 @@
open Import
include Usexp.Loc
(* TODO get rid of all this stuff once this parsing code moves to Usexp and
there will be no circular dependency *)
let int n = Usexp.Atom (Usexp.Atom.of_int n)
let string = Usexp.atom_or_quoted_string
let record l =
let open Usexp in
List (List.map l ~f:(fun (n, v) -> List [Atom(Atom.of_string n); v]))
let sexp_of_position_no_file (p : Lexing.position) =
record
[ "pos_lnum", int p.pos_lnum
; "pos_bol", int p.pos_bol
; "pos_cnum", int p.pos_cnum
]
let sexp_of_t t =
record (* TODO handle when pos_fname differs *)
[ "pos_fname", string t.start.pos_fname
; "start", sexp_of_position_no_file t.start
; "stop", sexp_of_position_no_file t.stop
]
let of_lexbuf lb =
{ start = Lexing.lexeme_start_p lb
; stop = Lexing.lexeme_end_p lb
}
let exnf t fmt =
Format.pp_open_box err_ppf 0;
Format.pp_print_as err_ppf 7 ""; (* "Error: " *)
kerrf (fmt^^ "@]") ~f:(fun s -> Exn.Loc_error (t, s))
let fail t fmt =
Format.pp_print_as err_ppf 7 ""; (* "Error: " *)
kerrf fmt ~f:(fun s ->
raise (Exn.Loc_error (t, s)))
let fail_lex lb fmt =
fail (of_lexbuf lb) fmt
let fail_opt t fmt =
match t with
| None -> die fmt
| Some t -> fail t fmt
let in_file = Usexp.Loc.in_file
let of_pos (fname, lnum, cnum, enum) =
let pos : Lexing.position =
{ pos_fname = fname
; pos_lnum = lnum
; pos_cnum = cnum
; pos_bol = 0
}
in
{ start = pos
; stop = { pos with pos_cnum = enum }
}
let file_line path n =
Io.with_file_in ~binary:false path
~f:(fun ic ->
for _ = 1 to n - 1 do
ignore (input_line ic)
done;
input_line ic
)
let file_lines path ~start ~stop =
Io.with_file_in ~binary:true path
~f:(fun ic ->
let rec aux acc lnum =
if lnum > stop then
List.rev acc
else if lnum < start then
(ignore (input_line ic);
aux acc (lnum + 1))
else
let line = input_line ic in
aux ((string_of_int lnum, line) :: acc) (lnum + 1)
in
aux [] 1
)
let print ppf loc =
let { start; stop } = loc in
let start_c = start.pos_cnum - start.pos_bol in
let stop_c = stop.pos_cnum - start.pos_bol in
let num_lines = stop.pos_lnum - start.pos_lnum in
let pp_file_excerpt pp () =
let whole_file = start_c = 0 && stop_c = 0 in
if not whole_file then
let path = Path.of_string start.pos_fname in
if Path.exists path then
let line = file_line path start.pos_lnum in
if stop_c <= String.length line then
let len = stop_c - start_c in
Format.fprintf pp "%s\n%*s\n" line
stop_c
(String.make len '^')
else if num_lines <= 10 then
let lines = file_lines path ~start:start.pos_lnum ~stop:stop.pos_lnum in
let last_lnum = Option.map ~f:fst (List.last lines) in
let padding_width = Option.value_exn
(Option.map ~f:String.length last_lnum) in
List.iter ~f:(fun (lnum, l) ->
Format.fprintf pp "%*s: %s\n" padding_width lnum l)
lines
in
Format.fprintf ppf
"@{<loc>File \"%s\", line %d, characters %d-%d:@}@\n%a"
start.pos_fname start.pos_lnum start_c stop_c
pp_file_excerpt ()
let warn t fmt =
Errors.kerrf ~f:print_to_console
("%a@{<warning>Warning@}: " ^^ fmt ^^ "@.") print t
let to_file_colon_line t =
sprintf "%s:%d" t.start.pos_fname t.start.pos_lnum
let pp_file_colon_line ppf t =
Format.pp_print_string ppf (to_file_colon_line t)
let equal_position
{ Lexing.pos_fname = f_a; pos_lnum = l_a
; pos_bol = b_a; pos_cnum = c_a }
{ Lexing.pos_fname = f_b; pos_lnum = l_b
; pos_bol = b_b; pos_cnum = c_b }
=
let open Int.Infix in
String.equal f_a f_b
&& l_a = l_b
&& b_a = b_b
&& c_a = c_b
let equal
{ start = start_a ; stop = stop_a }
{ start = start_b ; stop = stop_b }
=
equal_position start_a start_b
&& equal_position stop_a stop_b

Some files were not shown because too many files have changed in this diff Show More