Merge pull request #896 from diml/syntax-versionning
Complete handling of syntax versioning
This commit is contained in:
commit
e7e662e0bd
|
@ -122,64 +122,94 @@ type t =
|
||||||
}
|
}
|
||||||
|
|
||||||
module Lang = struct
|
module Lang = struct
|
||||||
type t = Syntax.Version.t * Stanza.Parser.t list
|
type t =
|
||||||
|
{ syntax : Syntax.t
|
||||||
|
; stanzas : Stanza.Parser.t list
|
||||||
|
}
|
||||||
|
|
||||||
let make ver f = (ver, f)
|
type instance =
|
||||||
|
{ lang : t
|
||||||
|
; version : Syntax.Version.t
|
||||||
|
}
|
||||||
|
|
||||||
let langs = Hashtbl.create 32
|
let langs = Hashtbl.create 32
|
||||||
|
|
||||||
let register name versions =
|
let register syntax stanzas =
|
||||||
|
let name = Syntax.name syntax in
|
||||||
if Hashtbl.mem langs name then
|
if Hashtbl.mem langs name then
|
||||||
Exn.code_error "Dune_project.Lang.register: already registered"
|
Exn.code_error "Dune_project.Lang.register: already registered"
|
||||||
[ "name", Sexp.To_sexp.string name ];
|
[ "name", Sexp.To_sexp.string name ];
|
||||||
Hashtbl.add langs name (Syntax.Versioned_parser.make versions)
|
Hashtbl.add langs name { syntax; stanzas }
|
||||||
|
|
||||||
let parse first_line =
|
let parse first_line =
|
||||||
let { Dune_lexer.
|
let { Dune_lexer.
|
||||||
lang = (name_loc, name)
|
lang = (name_loc, name)
|
||||||
; version = (ver_loc, ver)
|
; version = (ver_loc, ver)
|
||||||
} = first_line
|
} = first_line
|
||||||
in
|
in
|
||||||
let ver =
|
let ver =
|
||||||
Sexp.Of_sexp.parse Syntax.Version.t Univ_map.empty
|
Sexp.Of_sexp.parse Syntax.Version.t Univ_map.empty
|
||||||
(Atom (ver_loc, Sexp.Atom.of_string ver)) in
|
(Atom (ver_loc, Sexp.Atom.of_string ver))
|
||||||
|
in
|
||||||
match Hashtbl.find langs name with
|
match Hashtbl.find langs name with
|
||||||
| None ->
|
| None ->
|
||||||
Loc.fail name_loc "Unknown language %S.%s" name
|
Loc.fail name_loc "Unknown language %S.%s" name
|
||||||
(hint name (Hashtbl.keys langs))
|
(hint name (Hashtbl.keys langs))
|
||||||
| Some versions ->
|
| Some t ->
|
||||||
Syntax.Versioned_parser.find_exn versions
|
Syntax.check_supported t.syntax (ver_loc, ver);
|
||||||
~loc:ver_loc ~data_version:ver
|
{ lang = t
|
||||||
|
; version = ver
|
||||||
|
}
|
||||||
|
|
||||||
let latest name =
|
let get_exn name =
|
||||||
let versions = Option.value_exn (Hashtbl.find langs name) in
|
let lang = Option.value_exn (Hashtbl.find langs name) in
|
||||||
Syntax.Versioned_parser.last versions
|
{ lang
|
||||||
|
; version = Syntax.greatest_supported_version lang.syntax
|
||||||
let version = fst
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
module Extension = struct
|
module Extension = struct
|
||||||
type t = Syntax.Version.t * Stanza.Parser.t list Sexp.Of_sexp.t
|
type t =
|
||||||
|
{ syntax : Syntax.t
|
||||||
|
; stanzas : Stanza.Parser.t list Sexp.Of_sexp.t
|
||||||
|
}
|
||||||
|
|
||||||
let make ver f = (ver, f)
|
type instance =
|
||||||
|
{ extension : t
|
||||||
|
; version : Syntax.Version.t
|
||||||
|
; loc : Loc.t
|
||||||
|
; parse_args : Stanza.Parser.t list Sexp.Of_sexp.t -> Stanza.Parser.t list
|
||||||
|
}
|
||||||
|
|
||||||
let extensions = Hashtbl.create 32
|
let extensions = Hashtbl.create 32
|
||||||
|
|
||||||
let register name versions =
|
let register syntax stanzas =
|
||||||
|
let name = Syntax.name syntax in
|
||||||
if Hashtbl.mem extensions name then
|
if Hashtbl.mem extensions name then
|
||||||
Exn.code_error "Dune_project.Extension.register: already registered"
|
Exn.code_error "Dune_project.Extension.register: already registered"
|
||||||
[ "name", Sexp.To_sexp.string name ];
|
[ "name", Sexp.To_sexp.string name ];
|
||||||
Hashtbl.add extensions name (Syntax.Versioned_parser.make versions)
|
Hashtbl.add extensions name { syntax; stanzas }
|
||||||
|
|
||||||
let lookup (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
|
Loc.fail name_loc "Unknown extension %S.%s" name
|
||||||
(hint name (Hashtbl.keys extensions))
|
(hint name (Hashtbl.keys extensions))
|
||||||
| Some versions ->
|
| Some t ->
|
||||||
Syntax.Versioned_parser.find_exn versions ~loc:ver_loc ~data_version:ver
|
Syntax.check_supported t.syntax (ver_loc, ver);
|
||||||
|
{ extension = t
|
||||||
|
; version = ver
|
||||||
|
; loc
|
||||||
|
; parse_args
|
||||||
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let make_parsing_context ~(lang : Lang.instance) ~extensions =
|
||||||
|
let acc = Univ_map.singleton (Syntax.key lang.lang.syntax) lang.version in
|
||||||
|
List.fold_left extensions ~init:acc
|
||||||
|
~f:(fun acc (ext : Extension.instance) ->
|
||||||
|
Univ_map.add acc (Syntax.key ext.extension.syntax) ext.version)
|
||||||
|
|
||||||
let key = Univ_map.Key.create ()
|
let key = Univ_map.Key.create ()
|
||||||
let set t = Sexp.Of_sexp.set key t
|
let set t = Sexp.Of_sexp.set key t
|
||||||
let get_exn () =
|
let get_exn () =
|
||||||
|
@ -197,12 +227,15 @@ let get_local_path p =
|
||||||
| Local p -> p
|
| Local p -> p
|
||||||
|
|
||||||
let anonymous = lazy (
|
let anonymous = lazy (
|
||||||
|
let lang = Lang.get_exn "dune" in
|
||||||
|
let parsing_context = make_parsing_context ~lang ~extensions:[] in
|
||||||
{ kind = Dune
|
{ kind = Dune
|
||||||
; name = Name.anonymous_root
|
; name = Name.anonymous_root
|
||||||
; packages = Package.Name.Map.empty
|
; packages = Package.Name.Map.empty
|
||||||
; root = get_local_path Path.root
|
; root = get_local_path Path.root
|
||||||
; version = None
|
; version = None
|
||||||
; stanza_parser = Sexp.Of_sexp.sum (snd (Lang.latest "dune"))
|
; stanza_parser =
|
||||||
|
Sexp.Of_sexp.(set_many parsing_context (sum lang.lang.stanzas))
|
||||||
; project_file = None
|
; project_file = None
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -230,7 +263,7 @@ let name ~dir ~packages =
|
||||||
| Some x -> return x
|
| Some x -> return x
|
||||||
| None -> return (default_name ~dir ~packages)
|
| None -> return (default_name ~dir ~packages)
|
||||||
|
|
||||||
let parse ~dir ~lang_stanzas ~packages ~file =
|
let parse ~dir ~lang ~packages ~file =
|
||||||
record
|
record
|
||||||
(name ~dir ~packages >>= fun name ->
|
(name ~dir ~packages >>= fun name ->
|
||||||
field_o "version" string >>= fun version ->
|
field_o "version" string >>= fun version ->
|
||||||
|
@ -238,41 +271,55 @@ let parse ~dir ~lang_stanzas ~packages ~file =
|
||||||
(loc >>= fun loc ->
|
(loc >>= fun loc ->
|
||||||
located string >>= fun name ->
|
located string >>= fun name ->
|
||||||
located Syntax.Version.t >>= fun ver ->
|
located Syntax.Version.t >>= fun ver ->
|
||||||
Extension.lookup name ver >>= fun stanzas ->
|
(* We don't parse the arguments quite yet as we want to set
|
||||||
return (snd name, (loc, stanzas)))
|
the version of extensions before parsing them. *)
|
||||||
|
capture >>= fun parse_args ->
|
||||||
|
return (Extension.instantiate ~loc ~parse_args name ver))
|
||||||
>>= fun extensions ->
|
>>= fun extensions ->
|
||||||
let extensions_stanzas =
|
match
|
||||||
match String.Map.of_list extensions with
|
String.Map.of_list
|
||||||
| Error (name, _, (loc, _)) ->
|
(List.map extensions ~f:(fun (e : Extension.instance) ->
|
||||||
Loc.fail loc "Extension %S specified for the second time." name
|
(Syntax.name e.extension.syntax, e.loc)))
|
||||||
| Ok _ ->
|
with
|
||||||
List.concat_map extensions ~f:(fun (_, (_, x)) -> x)
|
| Error (name, _, loc) ->
|
||||||
in
|
Loc.fail loc "Extension %S specified for the second time." name
|
||||||
return
|
| Ok _ ->
|
||||||
{ kind = Dune
|
let parsing_context = make_parsing_context ~lang ~extensions in
|
||||||
; name
|
let stanzas =
|
||||||
; root = get_local_path dir
|
List.concat
|
||||||
; version
|
(lang.lang.stanzas ::
|
||||||
; packages
|
List.map extensions ~f:(fun (ext : Extension.instance) ->
|
||||||
; stanza_parser = Sexp.Of_sexp.sum (lang_stanzas @ extensions_stanzas)
|
ext.parse_args
|
||||||
; project_file = Some file
|
(Sexp.Of_sexp.set_many parsing_context ext.extension.stanzas)))
|
||||||
})
|
in
|
||||||
|
return
|
||||||
|
{ kind = Dune
|
||||||
|
; name
|
||||||
|
; root = get_local_path dir
|
||||||
|
; version
|
||||||
|
; packages
|
||||||
|
; stanza_parser = Sexp.Of_sexp.(set_many parsing_context (sum stanzas))
|
||||||
|
; project_file = Some file
|
||||||
|
})
|
||||||
|
|
||||||
let load_dune_project ~dir packages =
|
let load_dune_project ~dir packages =
|
||||||
let fname = Path.relative dir filename in
|
let fname = Path.relative dir filename in
|
||||||
Io.with_lexbuf_from_file fname ~f:(fun lb ->
|
Io.with_lexbuf_from_file fname ~f:(fun lb ->
|
||||||
let lang_stanzas = Lang.parse (Dune_lexer.first_line lb) in
|
let lang = Lang.parse (Dune_lexer.first_line lb) in
|
||||||
let sexp = Sexp.Parser.parse lb ~mode:Many_as_one in
|
let sexp = Sexp.Parser.parse lb ~mode:Many_as_one in
|
||||||
Sexp.Of_sexp.parse (parse ~dir ~lang_stanzas ~packages ~file:fname)
|
Sexp.Of_sexp.parse (parse ~dir ~lang ~packages ~file:fname)
|
||||||
Univ_map.empty sexp)
|
Univ_map.empty sexp)
|
||||||
|
|
||||||
let make_jbuilder_project ~dir packages =
|
let make_jbuilder_project ~dir packages =
|
||||||
|
let lang = Lang.get_exn "dune" in
|
||||||
|
let parsing_context = make_parsing_context ~lang ~extensions:[] in
|
||||||
{ kind = Jbuilder
|
{ kind = Jbuilder
|
||||||
; name = default_name ~dir ~packages
|
; name = default_name ~dir ~packages
|
||||||
; root = get_local_path dir
|
; root = get_local_path dir
|
||||||
; version = None
|
; version = None
|
||||||
; packages
|
; packages
|
||||||
; stanza_parser = Sexp.Of_sexp.sum (snd (Lang.latest "dune"))
|
; stanza_parser =
|
||||||
|
Sexp.Of_sexp.(set_many parsing_context (sum lang.lang.stanzas))
|
||||||
; project_file = None
|
; project_file = None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,8 +358,8 @@ let project_file t =
|
||||||
| Some file -> file
|
| Some file -> file
|
||||||
| None ->
|
| None ->
|
||||||
let file = Path.relative (Path.of_local t.root) filename in
|
let file = Path.relative (Path.of_local t.root) filename in
|
||||||
let maj, min = fst (Lang.latest "dune") in
|
let ver = (Lang.get_exn "dune").version in
|
||||||
let s = sprintf "(lang dune %d.%d)" maj min in
|
let s = sprintf "(lang dune %s)" (Syntax.Version.to_string ver) in
|
||||||
notify_user
|
notify_user
|
||||||
(sprintf "creating file %s with this contents: %s"
|
(sprintf "creating file %s with this contents: %s"
|
||||||
(Path.to_string_maybe_quoted file) s);
|
(Path.to_string_maybe_quoted file) s);
|
||||||
|
|
|
@ -41,42 +41,25 @@ type t = private
|
||||||
}
|
}
|
||||||
|
|
||||||
module Lang : sig
|
module Lang : sig
|
||||||
(** One version of a language *)
|
(** [register id stanzas_parser] register a new language. Users will
|
||||||
type t
|
select this language by writing:
|
||||||
|
|
||||||
(** [make version stanzas_parser] defines one version of a
|
|
||||||
language. Users will select this language by writing:
|
|
||||||
|
|
||||||
{[ (lang <name> <version>) ]}
|
{[ (lang <name> <version>) ]}
|
||||||
|
|
||||||
as the first line of their [dune-project] file. [stanza_parsers]
|
as the first line of their [dune-project] file. [stanza_parsers]
|
||||||
defines what stanzas the user can write in [dune] files. *)
|
defines what stanzas the user can write in [dune] files. *)
|
||||||
val make : Syntax.Version.t -> Stanza.Parser.t list -> t
|
val register : Syntax.t -> Stanza.Parser.t list -> unit
|
||||||
|
|
||||||
val version : t -> Syntax.Version.t
|
|
||||||
|
|
||||||
(** Register all the supported versions of a language *)
|
|
||||||
val register : string -> t list -> unit
|
|
||||||
|
|
||||||
(** Latest version of the following language *)
|
|
||||||
val latest : string -> t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Extension : sig
|
module Extension : sig
|
||||||
(** One version of an extension *)
|
(** [register id parser] registers a new extension. Users will
|
||||||
type t
|
|
||||||
|
|
||||||
(** [make version parser] defines one version of an extension. Users will
|
|
||||||
enable this extension by writing:
|
enable this extension by writing:
|
||||||
|
|
||||||
{[ (using <name> <version> <args>) ]}
|
{[ (using <name> <version> <args>) ]}
|
||||||
|
|
||||||
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 make : Syntax.Version.t -> Stanza.Parser.t list Sexp.Of_sexp.t -> t
|
val register : Syntax.t -> Stanza.Parser.t list Sexp.Of_sexp.t -> unit
|
||||||
|
|
||||||
(** Register all the supported versions of an extension *)
|
|
||||||
val register : string -> t list -> unit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(** Load a project description from the following directory. [files]
|
(** Load a project description from the following directory. [files]
|
||||||
|
|
|
@ -22,6 +22,14 @@ module Backend = struct
|
||||||
|
|
||||||
let loc t = t.loc
|
let loc t = t.loc
|
||||||
|
|
||||||
|
(* The syntax of the driver sub-system is part of the main dune
|
||||||
|
syntax, so we simply don't create a new one.
|
||||||
|
|
||||||
|
If we wanted to make the ppx system an extension, then we
|
||||||
|
would create a new one.
|
||||||
|
*)
|
||||||
|
let syntax = Jbuild.syntax
|
||||||
|
|
||||||
open Sexp.Of_sexp
|
open Sexp.Of_sexp
|
||||||
|
|
||||||
let parse =
|
let parse =
|
||||||
|
@ -41,11 +49,6 @@ module Backend = struct
|
||||||
; generate_runner
|
; generate_runner
|
||||||
; extends
|
; extends
|
||||||
})
|
})
|
||||||
|
|
||||||
let parsers =
|
|
||||||
Syntax.Versioned_parser.make
|
|
||||||
[ (1, 0), parse
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
type t =
|
type t =
|
||||||
|
@ -125,6 +128,8 @@ include Sub_system.Register_end_point(
|
||||||
let loc t = t.loc
|
let loc t = t.loc
|
||||||
let backends t = Option.map t.backend ~f:(fun x -> [x])
|
let backends t = Option.map t.backend ~f:(fun x -> [x])
|
||||||
|
|
||||||
|
let syntax = Jbuild.syntax
|
||||||
|
|
||||||
open Sexp.Of_sexp
|
open Sexp.Of_sexp
|
||||||
|
|
||||||
let parse =
|
let parse =
|
||||||
|
@ -145,11 +150,6 @@ include Sub_system.Register_end_point(
|
||||||
; backend
|
; backend
|
||||||
; libraries
|
; libraries
|
||||||
})
|
})
|
||||||
|
|
||||||
let parsers =
|
|
||||||
Syntax.Versioned_parser.make
|
|
||||||
[ (1, 0), parse
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let gen_rules c ~(info:Info.t) ~backends =
|
let gen_rules c ~(info:Info.t) ~backends =
|
||||||
|
|
|
@ -20,12 +20,11 @@ let parse_sub_systems sexps =
|
||||||
Loc.fail loc "%S present twice" (Sub_system_name.to_string name))
|
Loc.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) = Jbuild.Sub_system_info.get name in
|
let (module M) = Jbuild.Sub_system_info.get name in
|
||||||
let vloc, ver = version in
|
Syntax.check_supported M.syntax version;
|
||||||
let parser =
|
let parsing_context =
|
||||||
Syntax.Versioned_parser.find_exn M.parsers ~loc:vloc
|
Univ_map.singleton (Syntax.key M.syntax) (snd version)
|
||||||
~data_version:ver
|
|
||||||
in
|
in
|
||||||
M.T (Sexp.Of_sexp.parse parser Univ_map.empty data))
|
M.T (Sexp.Of_sexp.parse M.parse parsing_context data))
|
||||||
|
|
||||||
let of_sexp =
|
let of_sexp =
|
||||||
let open Sexp.Of_sexp in
|
let open Sexp.Of_sexp in
|
||||||
|
|
|
@ -5,6 +5,12 @@ open Sexp.Of_sexp
|
||||||
syntax for the various supported version of the specification.
|
syntax for the various supported version of the specification.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
|
let syntax =
|
||||||
|
Syntax.create ~name:"dune" ~desc:"the dune language"
|
||||||
|
[ (0, 0) (* Jbuild syntax *)
|
||||||
|
; (1, 0)
|
||||||
|
]
|
||||||
|
|
||||||
(* Deprecated *)
|
(* Deprecated *)
|
||||||
module Jbuild_version = struct
|
module Jbuild_version = struct
|
||||||
type t =
|
type t =
|
||||||
|
@ -575,9 +581,10 @@ module Sub_system_info = 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 name : Sub_system_name.t
|
val name : Sub_system_name.t
|
||||||
val loc : t -> Loc.t
|
val loc : t -> Loc.t
|
||||||
val parsers : t Sexp.Of_sexp.t Syntax.Versioned_parser.t
|
val syntax : Syntax.t
|
||||||
|
val parse : t Sexp.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
|
||||||
|
@ -588,8 +595,6 @@ module Sub_system_info = struct
|
||||||
module Register(M : S) : sig end = struct
|
module Register(M : S) : sig end = struct
|
||||||
open M
|
open M
|
||||||
|
|
||||||
let parse = snd (Syntax.Versioned_parser.last M.parsers)
|
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
match Sub_system_name.Table.get all name with
|
match Sub_system_name.Table.get all name with
|
||||||
| Some _ ->
|
| Some _ ->
|
||||||
|
@ -902,15 +907,11 @@ module Executables = struct
|
||||||
; buildable : Buildable.t
|
; buildable : Buildable.t
|
||||||
}
|
}
|
||||||
|
|
||||||
let common names public_names ~syntax ~multi =
|
let common names public_names ~multi =
|
||||||
Buildable.t >>= fun buildable ->
|
Buildable.t >>= fun buildable ->
|
||||||
(match (syntax : File_tree.Dune_file.Kind.t) with
|
field "link_executables" ~default:true
|
||||||
| Dune ->
|
(Syntax.deleted_in syntax (1, 0) >>> bool)
|
||||||
return ()
|
>>= fun (_ : bool) ->
|
||||||
| Jbuild ->
|
|
||||||
field "link_executables" bool ~default:true >>= fun _ ->
|
|
||||||
return ())
|
|
||||||
>>= fun () ->
|
|
||||||
field "link_deps" (list Dep_conf.t) ~default:[] >>= fun link_deps ->
|
field "link_deps" (list Dep_conf.t) ~default:[] >>= fun link_deps ->
|
||||||
field_oslu "link_flags" >>= fun link_flags ->
|
field_oslu "link_flags" >>= fun link_flags ->
|
||||||
field "modes" Link_mode.Set.t ~default:Link_mode.Set.default
|
field "modes" Link_mode.Set.t ~default:Link_mode.Set.default
|
||||||
|
@ -982,7 +983,7 @@ module Executables = struct
|
||||||
| "-" -> None
|
| "-" -> None
|
||||||
| s -> Some s
|
| s -> Some s
|
||||||
|
|
||||||
let multi ~syntax =
|
let multi =
|
||||||
record
|
record
|
||||||
(field "names" (list (located string)) >>= fun names ->
|
(field "names" (list (located string)) >>= fun names ->
|
||||||
map_validate (field_o "public_names" (list public_name)) ~f:(function
|
map_validate (field_o "public_names" (list public_name)) ~f:(function
|
||||||
|
@ -994,13 +995,13 @@ module Executables = struct
|
||||||
Error "The list of public names must be of the same \
|
Error "The list of public names must be of the same \
|
||||||
length as the list of names")
|
length as the list of names")
|
||||||
>>= fun public_names ->
|
>>= fun public_names ->
|
||||||
common ~syntax names public_names ~multi:true)
|
common names public_names ~multi:true)
|
||||||
|
|
||||||
let single ~syntax =
|
let single =
|
||||||
record
|
record
|
||||||
(field "name" (located string) >>= fun name ->
|
(field "name" (located string) >>= fun name ->
|
||||||
field_o "public_name" string >>= fun public_name ->
|
field_o "public_name" string >>= fun public_name ->
|
||||||
common ~syntax [name] [public_name] ~multi:false)
|
common [name] [public_name] ~multi:false)
|
||||||
end
|
end
|
||||||
|
|
||||||
module Rule = struct
|
module Rule = struct
|
||||||
|
@ -1289,12 +1290,12 @@ module Stanzas = struct
|
||||||
|
|
||||||
type constructors = (string * Stanza.t list Sexp.Of_sexp.t) list
|
type constructors = (string * Stanza.t list Sexp.Of_sexp.t) list
|
||||||
|
|
||||||
let common ~syntax : constructors =
|
let stanzas : constructors =
|
||||||
[ "library",
|
[ "library",
|
||||||
(Library.t >>| fun x ->
|
(Library.t >>| fun x ->
|
||||||
[Library x])
|
[Library x])
|
||||||
; "executable" , Executables.single ~syntax >>| execs
|
; "executable" , Executables.single >>| execs
|
||||||
; "executables", Executables.multi ~syntax >>| execs
|
; "executables", Executables.multi >>| execs
|
||||||
; "rule",
|
; "rule",
|
||||||
(loc >>= fun loc ->
|
(loc >>= fun loc ->
|
||||||
Rule.t >>| fun x ->
|
Rule.t >>| fun x ->
|
||||||
|
@ -1330,26 +1331,21 @@ module Stanzas = struct
|
||||||
; "documentation",
|
; "documentation",
|
||||||
(Documentation.t >>| fun d ->
|
(Documentation.t >>| fun d ->
|
||||||
[Documentation d])
|
[Documentation d])
|
||||||
]
|
; "jbuild_version",
|
||||||
|
(Syntax.deleted_in syntax (1, 0) >>= fun () ->
|
||||||
let dune =
|
Jbuild_version.t >>| fun _ -> [])
|
||||||
common ~syntax:Dune @
|
; "env",
|
||||||
[ "env",
|
(Syntax.since syntax (1, 0) >>= fun () ->
|
||||||
(loc >>= fun loc ->
|
loc >>= fun loc ->
|
||||||
repeat Env.rule >>| fun rules ->
|
repeat Env.rule >>| fun rules ->
|
||||||
[Env { loc; rules }])
|
[Env { loc; rules }])
|
||||||
]
|
]
|
||||||
|
|
||||||
let jbuild =
|
let jbuild_parser =
|
||||||
common ~syntax:Jbuild @
|
Syntax.set syntax (0, 0) (sum stanzas)
|
||||||
[ "jbuild_version", (Jbuild_version.t >>| fun _ -> [])
|
|
||||||
]
|
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
let open Dune_project.Lang in
|
Dune_project.Lang.register syntax stanzas
|
||||||
register "dune"
|
|
||||||
[ make (1, 0) dune
|
|
||||||
]
|
|
||||||
|
|
||||||
exception Include_loop of Path.t * (Loc.t * Path.t) list
|
exception Include_loop of Path.t * (Loc.t * Path.t) list
|
||||||
|
|
||||||
|
@ -1373,7 +1369,7 @@ module Stanzas = struct
|
||||||
let stanza_parser =
|
let stanza_parser =
|
||||||
Dune_project.set project
|
Dune_project.set project
|
||||||
(match (kind : File_tree.Dune_file.Kind.t) with
|
(match (kind : File_tree.Dune_file.Kind.t) with
|
||||||
| Jbuild -> sum jbuild
|
| Jbuild -> jbuild_parser
|
||||||
| Dune -> project.stanza_parser)
|
| Dune -> project.stanza_parser)
|
||||||
in
|
in
|
||||||
let stanzas =
|
let stanzas =
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
|
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
|
(** Syntax identifier for the Dune language. [(0, X)] correspond to
|
||||||
|
the Jbuild language while versions from [(1, 0)] correspond to the
|
||||||
|
Dune one. *)
|
||||||
|
val syntax : Syntax.t
|
||||||
|
|
||||||
(** Ppx preprocessors *)
|
(** Ppx preprocessors *)
|
||||||
module Pp : sig
|
module Pp : sig
|
||||||
type t = private string
|
type t = private string
|
||||||
|
@ -139,10 +144,14 @@ module Sub_system_info : sig
|
||||||
(** Name of the sub-system *)
|
(** Name of the sub-system *)
|
||||||
val name : Sub_system_name.t
|
val name : Sub_system_name.t
|
||||||
|
|
||||||
(** Location of the S-expression passed to [of_sexp] or [short]. *)
|
(** Location of the parameters in the jbuild/dune file. *)
|
||||||
val loc : t -> Loc.t
|
val loc : t -> Loc.t
|
||||||
|
|
||||||
val parsers : t Sexp.Of_sexp.t Syntax.Versioned_parser.t
|
(** Syntax for jbuild/dune files *)
|
||||||
|
val syntax : Syntax.t
|
||||||
|
|
||||||
|
(** Parse parameters written by the user in jbuid/dune files *)
|
||||||
|
val parse : t Sexp.Of_sexp.t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Register(M : S) : sig end
|
module Register(M : S) : sig end
|
||||||
|
|
|
@ -32,6 +32,14 @@ module Driver = struct
|
||||||
|
|
||||||
let loc t = t.loc
|
let loc t = t.loc
|
||||||
|
|
||||||
|
(* The syntax of the driver sub-system is part of the main dune
|
||||||
|
syntax, so we simply don't create a new one.
|
||||||
|
|
||||||
|
If we wanted to make the ppx system an extension, then we
|
||||||
|
would create a new one.
|
||||||
|
*)
|
||||||
|
let syntax = Jbuild.syntax
|
||||||
|
|
||||||
open Sexp.Of_sexp
|
open Sexp.Of_sexp
|
||||||
|
|
||||||
let parse =
|
let parse =
|
||||||
|
@ -49,10 +57,6 @@ module Driver = struct
|
||||||
; main
|
; main
|
||||||
; replaces
|
; replaces
|
||||||
})
|
})
|
||||||
|
|
||||||
let parsers =
|
|
||||||
Syntax.Versioned_parser.make
|
|
||||||
[ (1, 0), parse ]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(* The [lib] field is lazy so that we don't need to fill it for
|
(* The [lib] field is lazy so that we don't need to fill it for
|
||||||
|
|
|
@ -116,4 +116,7 @@ module Make(Key : Comparable.S) : S with type key = Key.t = struct
|
||||||
| None -> assert false
|
| None -> assert false
|
||||||
| Some data -> f key data)
|
| Some data -> f key data)
|
||||||
let filter_map t ~f = filter_mapi t ~f:(fun _ x -> f x)
|
let filter_map t ~f = filter_mapi t ~f:(fun _ x -> f x)
|
||||||
|
|
||||||
|
let superpose a b =
|
||||||
|
union a b ~f:(fun _ _ y -> Some y)
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,10 @@ module type S = sig
|
||||||
-> f:(key -> 'a -> 'a -> 'a option)
|
-> f:(key -> 'a -> 'a -> 'a option)
|
||||||
-> 'a t
|
-> 'a t
|
||||||
|
|
||||||
|
(** [superpose a b] is [b] augmented with bindings of [a] that are
|
||||||
|
not in [b]. *)
|
||||||
|
val superpose : 'a t -> 'a t -> 'a t
|
||||||
|
|
||||||
val compare : 'a t -> 'a t -> compare:('a -> 'a -> Ordering.t) -> Ordering.t
|
val compare : 'a t -> 'a t -> compare:('a -> 'a -> Ordering.t) -> Ordering.t
|
||||||
val equal : 'a t -> 'a t -> equal:('a -> 'a -> bool) -> bool
|
val equal : 'a t -> 'a t -> equal:('a -> 'a -> bool) -> bool
|
||||||
|
|
||||||
|
|
|
@ -141,6 +141,14 @@ module Of_sexp = struct
|
||||||
| Fields (loc, cstr, uc) ->
|
| Fields (loc, cstr, uc) ->
|
||||||
t (Fields (loc, cstr, Univ_map.add uc key v)) state
|
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 ->
|
let loc : type k. k context -> k -> Loc.t * k = fun ctx state ->
|
||||||
match ctx with
|
match ctx with
|
||||||
| Values (loc, _, _) -> (loc, state)
|
| Values (loc, _, _) -> (loc, state)
|
||||||
|
@ -191,6 +199,12 @@ module Of_sexp = struct
|
||||||
let ctx = Values (Ast.loc sexp, None, context) in
|
let ctx = Values (Ast.loc sexp, None, context) in
|
||||||
result ctx (t ctx [sexp])
|
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, _)) =
|
let end_of_list (Values (loc, cstr, _)) =
|
||||||
match cstr with
|
match cstr with
|
||||||
| None ->
|
| None ->
|
||||||
|
@ -494,6 +508,16 @@ module Of_sexp = struct
|
||||||
(x, [])
|
(x, [])
|
||||||
|
|
||||||
let record t = enter (fields t)
|
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)
|
||||||
end
|
end
|
||||||
|
|
||||||
module type Sexpable = sig
|
module type Sexpable = sig
|
||||||
|
|
|
@ -109,6 +109,7 @@ module Of_sexp : sig
|
||||||
(** Access to the context *)
|
(** Access to the context *)
|
||||||
val get : 'a Univ_map.Key.t -> ('a option, _) parser
|
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 set : 'a Univ_map.Key.t -> 'a -> ('b, 'k) parser -> ('b, 'k) parser
|
||||||
|
val set_many : Univ_map.t -> ('a, 'k) parser -> ('a, 'k) parser
|
||||||
|
|
||||||
(** Return the location of the list currently being parsed. *)
|
(** Return the location of the list currently being parsed. *)
|
||||||
val loc : (Loc.t, _) parser
|
val loc : (Loc.t, _) parser
|
||||||
|
@ -117,10 +118,21 @@ module Of_sexp : sig
|
||||||
S-expressions to parse *)
|
S-expressions to parse *)
|
||||||
val eos : (bool, _) parser
|
val eos : (bool, _) parser
|
||||||
|
|
||||||
|
(** 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
|
(** [repeat t] use [t] to consume all remaning elements of the input
|
||||||
until the end of sequence is reached. *)
|
until the end of sequence is reached. *)
|
||||||
val repeat : 'a t -> 'a list t
|
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
|
(** [enter t] expect the next element of the input to be a list and
|
||||||
parse its contents with [t]. *)
|
parse its contents with [t]. *)
|
||||||
val enter : 'a t -> 'a t
|
val enter : 'a t -> 'a t
|
||||||
|
|
|
@ -71,3 +71,6 @@ let find_exn t key =
|
||||||
let eq = Key.eq key' key in
|
let eq = Key.eq key' key in
|
||||||
Eq.cast eq v
|
Eq.cast eq v
|
||||||
|
|
||||||
|
let singleton key v = Int.Map.singleton (Key.id key) (Binding.T (key, v))
|
||||||
|
|
||||||
|
let superpose = Int.Map.superpose
|
||||||
|
|
|
@ -17,3 +17,8 @@ val add : t -> 'a Key.t -> 'a -> t
|
||||||
val remove : t -> 'a Key.t -> t
|
val remove : t -> 'a Key.t -> t
|
||||||
val find : t -> 'a Key.t -> 'a option
|
val find : t -> 'a Key.t -> 'a option
|
||||||
val find_exn : t -> 'a Key.t -> 'a
|
val find_exn : t -> 'a Key.t -> 'a
|
||||||
|
val singleton : 'a Key.t -> 'a -> t
|
||||||
|
|
||||||
|
(** [superpose a b] is [b] augmented with bindings of [a] that are not
|
||||||
|
in [b]. *)
|
||||||
|
val superpose : t -> t -> t
|
||||||
|
|
127
src/syntax.ml
127
src/syntax.ml
|
@ -23,38 +23,115 @@ module Version = struct
|
||||||
pa = da && db <= pb
|
pa = da && db <= pb
|
||||||
end
|
end
|
||||||
|
|
||||||
module Versioned_parser = struct
|
module Supported_versions = struct
|
||||||
type 'a t = (int * 'a) Int.Map.t
|
type t = int Int.Map.t
|
||||||
|
|
||||||
let make l =
|
let make l : t =
|
||||||
if List.is_empty l then
|
|
||||||
Exn.code_error "Syntax.Versioned_parser.make got empty list" [];
|
|
||||||
match
|
match
|
||||||
List.map l ~f:(fun ((major, minor), p) -> (major, (minor, p)))
|
List.map l ~f:(fun (major, minor) -> (major, minor))
|
||||||
|> Int.Map.of_list
|
|> Int.Map.of_list
|
||||||
with
|
with
|
||||||
| Ok x -> x
|
| Ok x -> x
|
||||||
| Error _ ->
|
| Error _ ->
|
||||||
Exn.code_error
|
Exn.code_error
|
||||||
"Syntax.Versioned_parser.make"
|
"Syntax.create"
|
||||||
[ "versions", Sexp.To_sexp.list Version.sexp_of_t (List.map l ~f:fst) ]
|
[ "versions", Sexp.To_sexp.list Version.sexp_of_t l ]
|
||||||
|
|
||||||
let last t =
|
let greatest_supported_version t = Option.value_exn (Int.Map.max_binding t)
|
||||||
let major, (minor, p) = Option.value_exn (Int.Map.max_binding t) in
|
|
||||||
((major, minor), p)
|
|
||||||
|
|
||||||
let find_exn t ~loc ~data_version:(major, minor) =
|
let is_supported t (major, minor) =
|
||||||
match
|
match Int.Map.find t major with
|
||||||
Option.bind (Int.Map.find t major) ~f:(fun (minor', p) ->
|
| Some minor' -> minor' >= minor
|
||||||
Option.some_if (minor' >= minor) p)
|
| None -> false
|
||||||
with
|
|
||||||
| None ->
|
let supported_ranges t =
|
||||||
Loc.fail loc "Version %s is not supported.\n\
|
Int.Map.to_list t |> List.map ~f:(fun (major, minor) ->
|
||||||
Supported versions:\n\
|
((major, 0), (major, minor)))
|
||||||
%s"
|
|
||||||
(Version.to_string (major, minor))
|
|
||||||
(String.concat ~sep:"\n"
|
|
||||||
(Int.Map.to_list t |> List.map ~f:(fun (major, (minor, _)) ->
|
|
||||||
sprintf "- %u.0 to %u.%u" major major minor)))
|
|
||||||
| Some p -> p
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
type t =
|
||||||
|
{ name : string
|
||||||
|
; desc : string
|
||||||
|
; key : Version.t Univ_map.Key.t
|
||||||
|
; supported_versions : Supported_versions.t
|
||||||
|
}
|
||||||
|
|
||||||
|
let create ~name ~desc supported_versions =
|
||||||
|
{ name
|
||||||
|
; desc
|
||||||
|
; key = Univ_map.Key.create ()
|
||||||
|
; supported_versions = Supported_versions.make supported_versions
|
||||||
|
}
|
||||||
|
|
||||||
|
let name t = t.name
|
||||||
|
|
||||||
|
let check_supported t (loc, ver) =
|
||||||
|
if not (Supported_versions.is_supported t.supported_versions ver) then
|
||||||
|
Loc.fail loc "Version %s of %s is not supported.\n\
|
||||||
|
Supported versions:\n\
|
||||||
|
%s"
|
||||||
|
(Version.to_string ver) t.name
|
||||||
|
(String.concat ~sep:"\n"
|
||||||
|
(List.map (Supported_versions.supported_ranges t.supported_versions)
|
||||||
|
~f:(fun (a, b) ->
|
||||||
|
sprintf "- %s to %s"
|
||||||
|
(Version.to_string a)
|
||||||
|
(Version.to_string b))))
|
||||||
|
|
||||||
|
let greatest_supported_version t =
|
||||||
|
Supported_versions.greatest_supported_version t.supported_versions
|
||||||
|
|
||||||
|
let key t = t.key
|
||||||
|
|
||||||
|
open Sexp.Of_sexp
|
||||||
|
|
||||||
|
let set t ver parser =
|
||||||
|
set t.key ver parser
|
||||||
|
|
||||||
|
let get_exn t =
|
||||||
|
get t.key >>| function
|
||||||
|
| Some x -> x
|
||||||
|
| None ->
|
||||||
|
Exn.code_error "Syntax identifier is unset"
|
||||||
|
[ "name", Sexp.To_sexp.string t.name ]
|
||||||
|
|
||||||
|
let desc () =
|
||||||
|
kind >>| fun kind ->
|
||||||
|
match kind with
|
||||||
|
| Values (loc, None) -> (loc, "This syntax")
|
||||||
|
| Fields (loc, None) -> (loc, "This field")
|
||||||
|
| Values (loc, Some s) -> (loc, sprintf "'%s'" s)
|
||||||
|
| Fields (loc, Some s) -> (loc, sprintf "Field '%s'" s)
|
||||||
|
|
||||||
|
let deleted_in t ver =
|
||||||
|
get_exn t >>= fun current_ver ->
|
||||||
|
if current_ver < ver then
|
||||||
|
return ()
|
||||||
|
else begin
|
||||||
|
desc () >>= fun (loc, what) ->
|
||||||
|
Loc.fail loc
|
||||||
|
"%s was deleted in version %s of %s" what
|
||||||
|
(Version.to_string ver) t.desc
|
||||||
|
end
|
||||||
|
|
||||||
|
let renamed_in t ver ~to_ =
|
||||||
|
get_exn t >>= fun current_ver ->
|
||||||
|
if current_ver < ver then
|
||||||
|
return ()
|
||||||
|
else begin
|
||||||
|
desc () >>= fun (loc, what) ->
|
||||||
|
Loc.fail loc
|
||||||
|
"%s was renamed to '%s' in %s of %s" what to_
|
||||||
|
(Version.to_string ver) t.desc
|
||||||
|
end
|
||||||
|
|
||||||
|
let since t ver =
|
||||||
|
get_exn t >>= fun current_ver ->
|
||||||
|
if current_ver >= ver then
|
||||||
|
return ()
|
||||||
|
else begin
|
||||||
|
desc () >>= fun (loc, what) ->
|
||||||
|
Loc.fail loc
|
||||||
|
"%s is only available since version %s of %s" what
|
||||||
|
(Version.to_string ver) t.desc
|
||||||
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
|
(** Management of syntaxes *)
|
||||||
|
|
||||||
open Stdune
|
open Stdune
|
||||||
(** Versioned syntaxes *)
|
|
||||||
|
|
||||||
module Version : sig
|
module Version : sig
|
||||||
(** A syntax version.
|
(** A syntax version.
|
||||||
|
@ -11,20 +12,52 @@ module Version : sig
|
||||||
|
|
||||||
include Sexp.Sexpable with type t := t
|
include Sexp.Sexpable with type t := t
|
||||||
|
|
||||||
|
val to_string : t -> string
|
||||||
|
|
||||||
(** Whether the parser can read the data or not *)
|
(** Whether the parser can read the data or not *)
|
||||||
val can_read : parser_version:t -> data_version:t -> bool
|
val can_read : parser_version:t -> data_version:t -> bool
|
||||||
end
|
end
|
||||||
|
|
||||||
module Versioned_parser : sig
|
type t
|
||||||
(** Versioned parser *)
|
|
||||||
type 'a t
|
|
||||||
|
|
||||||
(** Create a versionned parser. There must be exactly one parser per
|
(** [create ~name ~desc supported_versions] defines a new
|
||||||
major version. *)
|
syntax. [supported_version] is the list of the last minor version
|
||||||
val make : (Version.t * 'a) list -> 'a t
|
of each supported major version. [desc] is used to describe what
|
||||||
|
this syntax represent in error messages. *)
|
||||||
|
val create : name:string -> desc:string -> Version.t list -> t
|
||||||
|
|
||||||
val last : 'a t -> Version.t * 'a
|
(** Return the name of the syntax. *)
|
||||||
|
val name : t -> string
|
||||||
|
|
||||||
(** Find a parser that can parse data of this version *)
|
(** Check that the given version is supported and raise otherwise. *)
|
||||||
val find_exn : 'a t -> loc:Loc.t -> data_version:Version.t -> 'a
|
val check_supported : t -> Loc.t * Version.t -> unit
|
||||||
end
|
|
||||||
|
val greatest_supported_version : t -> Version.t
|
||||||
|
|
||||||
|
(** {1 S-expression parsing} *)
|
||||||
|
|
||||||
|
(** {2 High-level functions} *)
|
||||||
|
|
||||||
|
(** Indicate the field/constructor being parsed was deleted in the
|
||||||
|
given version *)
|
||||||
|
val deleted_in : t -> Version.t -> (unit, _) Sexp.Of_sexp.parser
|
||||||
|
|
||||||
|
(** Indicate the field/constructor being parsed was renamed in the
|
||||||
|
given version *)
|
||||||
|
val renamed_in : t -> Version.t -> to_:string -> (unit, _) Sexp.Of_sexp.parser
|
||||||
|
|
||||||
|
(** Indicate the field/constructor being parsed was introduced in the
|
||||||
|
given version *)
|
||||||
|
val since : t -> Version.t -> (unit, _) Sexp.Of_sexp.parser
|
||||||
|
|
||||||
|
(** {2 Low-level functions} *)
|
||||||
|
|
||||||
|
val set
|
||||||
|
: t
|
||||||
|
-> Version.t
|
||||||
|
-> ('a, 'k) Sexp.Of_sexp.parser
|
||||||
|
-> ('a, 'k) Sexp.Of_sexp.parser
|
||||||
|
|
||||||
|
val get_exn : t -> (Version.t, 'k) Sexp.Of_sexp.parser
|
||||||
|
|
||||||
|
val key : t -> Version.t Univ_map.Key.t
|
||||||
|
|
|
@ -543,6 +543,14 @@
|
||||||
test-cases/select
|
test-cases/select
|
||||||
(progn (run ${exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))))
|
(progn (run ${exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))))
|
||||||
|
|
||||||
|
(alias
|
||||||
|
((name syntax-versioning)
|
||||||
|
(deps ((package dune) (files_recursively_in test-cases/syntax-versioning)))
|
||||||
|
(action
|
||||||
|
(chdir
|
||||||
|
test-cases/syntax-versioning
|
||||||
|
(progn (run ${exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))))
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
((name use-meta)
|
((name use-meta)
|
||||||
(deps ((package dune) (files_recursively_in test-cases/use-meta)))
|
(deps ((package dune) (files_recursively_in test-cases/use-meta)))
|
||||||
|
@ -623,6 +631,7 @@
|
||||||
(alias scope-bug)
|
(alias scope-bug)
|
||||||
(alias scope-ppx-bug)
|
(alias scope-ppx-bug)
|
||||||
(alias select)
|
(alias select)
|
||||||
|
(alias syntax-versioning)
|
||||||
(alias use-meta)
|
(alias use-meta)
|
||||||
(alias utop)))))
|
(alias utop)))))
|
||||||
|
|
||||||
|
@ -682,6 +691,7 @@
|
||||||
(alias scope-bug)
|
(alias scope-bug)
|
||||||
(alias scope-ppx-bug)
|
(alias scope-ppx-bug)
|
||||||
(alias select)
|
(alias select)
|
||||||
|
(alias syntax-versioning)
|
||||||
(alias use-meta)))))
|
(alias use-meta)))))
|
||||||
|
|
||||||
(alias ((name runtest-disabled) (deps ((alias reason)))))
|
(alias ((name runtest-disabled) (deps ((alias reason)))))
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
$ echo '(jbuild_version 1)' > dune
|
||||||
|
$ dune build
|
||||||
|
Info: creating file dune-project with this contents: (lang dune 1.0)
|
||||||
|
File "dune", line 1, characters 0-18:
|
||||||
|
Error: 'jbuild_version' was deleted in version 1.0 of the dune language
|
||||||
|
[1]
|
||||||
|
$ rm -f dune
|
||||||
|
|
||||||
|
$ echo '(jbuild_version 1)' > jbuild
|
||||||
|
$ dune build
|
||||||
|
$ rm -f jbuild
|
||||||
|
|
||||||
|
$ echo '(executable ((name x) (link_executables false)))' > dune
|
||||||
|
$ dune build
|
||||||
|
File "dune", line 1, characters 22-46:
|
||||||
|
Error: 'link_executables' was deleted in version 1.0 of the dune language
|
||||||
|
[1]
|
||||||
|
$ rm -f dune
|
Loading…
Reference in New Issue