Merge pull request #833 from rgrinberg/return-expand
Change return type of string expansions
This commit is contained in:
commit
93070c9a4d
|
@ -374,8 +374,8 @@ module Unexpanded = struct
|
||||||
| Left x -> map x
|
| Left x -> map x
|
||||||
| Right template ->
|
| Right template ->
|
||||||
match To_VE.expand dir template ~f with
|
match To_VE.expand dir template ~f with
|
||||||
| Left e -> special dir e
|
| Expansion e -> special dir e
|
||||||
| Right s -> generic dir s
|
| String s -> generic dir s
|
||||||
[@@inlined always]
|
[@@inlined always]
|
||||||
|
|
||||||
let string ~dir ~f x =
|
let string ~dir ~f x =
|
||||||
|
@ -465,9 +465,9 @@ module Unexpanded = struct
|
||||||
module E = struct
|
module E = struct
|
||||||
let expand ~generic ~special ~dir ~f template =
|
let expand ~generic ~special ~dir ~f template =
|
||||||
match To_VE.partial_expand dir template ~f with
|
match To_VE.partial_expand dir template ~f with
|
||||||
| Left (Left e) -> Left (special dir e)
|
| Expansion e -> Left (special dir e)
|
||||||
| Left (Right s) -> Left (generic dir s)
|
| String s -> Left (generic dir s)
|
||||||
| Right _ as x -> x
|
| Unexpanded x -> Right x
|
||||||
|
|
||||||
let string ~dir ~f x =
|
let string ~dir ~f x =
|
||||||
expand ~dir ~f x
|
expand ~dir ~f x
|
||||||
|
|
|
@ -62,7 +62,7 @@ let items_of_string s = of_tokens (Token.tokenise s)
|
||||||
let t : Sexp.Of_sexp.ast -> t = function
|
let t : Sexp.Of_sexp.ast -> t = function
|
||||||
| Atom(loc, A s) -> { items = items_of_string s; loc; quoted = false }
|
| Atom(loc, A s) -> { items = items_of_string s; loc; quoted = false }
|
||||||
| Quoted_string (loc, s) ->
|
| Quoted_string (loc, s) ->
|
||||||
{ items = items_of_string s; loc; quoted = true }
|
{ items = items_of_string s; loc; quoted = true }
|
||||||
| List _ as sexp -> Sexp.Of_sexp.of_sexp_error sexp "Atom expected"
|
| List _ as sexp -> Sexp.Of_sexp.of_sexp_error sexp "Atom expected"
|
||||||
|
|
||||||
let loc t = t.loc
|
let loc t = t.loc
|
||||||
|
@ -89,13 +89,13 @@ let sexp_of_ast t = Sexp.To_sexp.list sexp_of_item t.items
|
||||||
|
|
||||||
let fold t ~init ~f =
|
let fold t ~init ~f =
|
||||||
List.fold_left t.items ~init ~f:(fun acc item ->
|
List.fold_left t.items ~init ~f:(fun acc item ->
|
||||||
match item with
|
match item with
|
||||||
| Text _ -> acc
|
| Text _ -> acc
|
||||||
| Var (_, v) -> f acc t.loc v)
|
| Var (_, v) -> f acc t.loc v)
|
||||||
|
|
||||||
let iter t ~f = List.iter t.items ~f:(function
|
let iter t ~f = List.iter t.items ~f:(function
|
||||||
| Text _ -> ()
|
| Text _ -> ()
|
||||||
| Var (_, v) -> f t.loc v)
|
| Var (_, v) -> f t.loc v)
|
||||||
|
|
||||||
let vars t = fold t ~init:String.Set.empty ~f:(fun acc _ x -> String.Set.add acc x)
|
let vars t = fold t ~init:String.Set.empty ~f:(fun acc _ x -> String.Set.add acc x)
|
||||||
|
|
||||||
|
@ -116,6 +116,20 @@ let concat_rev = function
|
||||||
| [s] -> s
|
| [s] -> s
|
||||||
| l -> String.concat (List.rev l) ~sep:""
|
| l -> String.concat (List.rev l) ~sep:""
|
||||||
|
|
||||||
|
module Expand = struct
|
||||||
|
module Full = struct
|
||||||
|
type nonrec 'a t =
|
||||||
|
| Expansion of 'a
|
||||||
|
| String of string
|
||||||
|
end
|
||||||
|
module Partial = struct
|
||||||
|
type nonrec 'a t =
|
||||||
|
| Expansion of 'a
|
||||||
|
| String of string
|
||||||
|
| Unexpanded of t
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
module Expand_to(V: EXPANSION) = struct
|
module Expand_to(V: EXPANSION) = struct
|
||||||
|
|
||||||
let expand ctx t ~f =
|
let expand ctx t ~f =
|
||||||
|
@ -123,10 +137,10 @@ module Expand_to(V: EXPANSION) = struct
|
||||||
| [Var (syntax, v)] when not t.quoted ->
|
| [Var (syntax, v)] when not t.quoted ->
|
||||||
(* Unquoted single var *)
|
(* Unquoted single var *)
|
||||||
(match f t.loc v with
|
(match f t.loc v with
|
||||||
| Some e -> Left e
|
| Some e -> Expand.Full.Expansion e
|
||||||
| None -> Right (string_of_var syntax v))
|
| None -> Expand.Full.String (string_of_var syntax v))
|
||||||
| _ ->
|
| _ ->
|
||||||
Right (List.map t.items ~f:(function
|
Expand.Full.String (List.map t.items ~f:(function
|
||||||
| Text s -> s
|
| Text s -> s
|
||||||
| Var (syntax, v) ->
|
| Var (syntax, v) ->
|
||||||
match f t.loc v with
|
match f t.loc v with
|
||||||
|
@ -137,7 +151,7 @@ module Expand_to(V: EXPANSION) = struct
|
||||||
(string_of_var syntax v)
|
(string_of_var syntax v)
|
||||||
else V.to_string ctx x
|
else V.to_string ctx x
|
||||||
| None -> string_of_var syntax v)
|
| None -> string_of_var syntax v)
|
||||||
|> String.concat ~sep:"")
|
|> String.concat ~sep:"")
|
||||||
|
|
||||||
let partial_expand ctx t ~f =
|
let partial_expand ctx t ~f =
|
||||||
let commit_text acc_text acc =
|
let commit_text acc_text acc =
|
||||||
|
@ -148,25 +162,25 @@ module Expand_to(V: EXPANSION) = struct
|
||||||
match items with
|
match items with
|
||||||
| [] -> begin
|
| [] -> begin
|
||||||
match acc with
|
match acc with
|
||||||
| [] -> Left (Right (concat_rev acc_text))
|
| [] -> Expand.Partial.String (concat_rev acc_text)
|
||||||
| _ -> Right { t with items = List.rev (commit_text acc_text acc) }
|
| _ -> Unexpanded { t with items = List.rev (commit_text acc_text acc) }
|
||||||
end
|
end
|
||||||
| Text s :: items -> loop (s :: acc_text) acc items
|
| Text s :: items -> loop (s :: acc_text) acc items
|
||||||
| Var (syntax, v) as it :: items ->
|
| Var (syntax, v) as it :: items ->
|
||||||
match f t.loc v with
|
match f t.loc v with
|
||||||
| None -> loop [] (it :: commit_text acc_text acc) items
|
| None -> loop [] (it :: commit_text acc_text acc) items
|
||||||
| Some x ->
|
| Some x ->
|
||||||
if not t.quoted && V.is_multivalued x then
|
if not t.quoted && V.is_multivalued x then
|
||||||
Loc.fail t.loc "please quote the string containing the \
|
Loc.fail t.loc "please quote the string containing the \
|
||||||
list variable %s" (string_of_var syntax v)
|
list variable %s" (string_of_var syntax v)
|
||||||
else loop (V.to_string ctx x :: acc_text) acc items
|
else loop (V.to_string ctx x :: acc_text) acc items
|
||||||
in
|
in
|
||||||
match t.items with
|
match t.items with
|
||||||
| [Var (_, v)] when not t.quoted ->
|
| [Var (_, v)] when not t.quoted ->
|
||||||
(* Unquoted single var *)
|
(* Unquoted single var *)
|
||||||
(match f t.loc v with
|
(match f t.loc v with
|
||||||
| Some e -> Left (Left e)
|
| Some e -> Expand.Partial.Expansion e
|
||||||
| None -> Right t)
|
| None -> Expand.Partial.Unexpanded t)
|
||||||
| _ -> loop [] [] t.items
|
| _ -> loop [] [] t.items
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -180,12 +194,15 @@ end
|
||||||
module S = Expand_to(String_expansion)
|
module S = Expand_to(String_expansion)
|
||||||
|
|
||||||
let expand t ~f =
|
let expand t ~f =
|
||||||
match S.expand () t ~f with Left s | Right s -> s
|
match S.expand () t ~f with
|
||||||
|
| Expand.Full.String s
|
||||||
|
| Expansion s -> s
|
||||||
|
|
||||||
let partial_expand t ~f =
|
let partial_expand t ~f =
|
||||||
match S.partial_expand () t ~f with
|
match S.partial_expand () t ~f with
|
||||||
| Left (Left s | Right s) -> Left s
|
| Expand.Partial.Expansion s -> Left s
|
||||||
| Right _ as x -> x
|
| String s -> Left s
|
||||||
|
| Unexpanded s -> Right s
|
||||||
|
|
||||||
let to_string t =
|
let to_string t =
|
||||||
match t.items with
|
match t.items with
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
(** String with variables of the form ${...} or $(...)
|
(** String with variables of the form ${...} or $(...)
|
||||||
|
|
||||||
Variables cannot contain "${", "$(", ")" or "}". For instance in "$(cat ${x})", only
|
Variables cannot contain "${", "$(", ")" or "}". For instance in "$(cat
|
||||||
"${x}" will be considered a variable, the rest is text. *)
|
${x})", only "${x}" will be considered a variable, the rest is text. *)
|
||||||
|
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ type t
|
||||||
|
|
||||||
val t : t Sexp.Of_sexp.t
|
val t : t Sexp.Of_sexp.t
|
||||||
(** [t ast] takes an [ast] sexp and returns a string-with-vars. This
|
(** [t ast] takes an [ast] sexp and returns a string-with-vars. This
|
||||||
function distinguishes between unquoted variables — such as ${@} —
|
function distinguishes between unquoted variables — such as ${@} —
|
||||||
and quoted variables — such as "${@}". *)
|
and quoted variables — such as "${@}". *)
|
||||||
|
|
||||||
val loc : t -> Loc.t
|
val loc : t -> Loc.t
|
||||||
(** [loc t] returns the location of [t] — typically, in the jbuild file. *)
|
(** [loc t] returns the location of [t] — typically, in the jbuild file. *)
|
||||||
|
@ -25,9 +25,9 @@ val sexp_of_ast : t -> Sexp.t
|
||||||
val to_string : t -> string
|
val to_string : t -> string
|
||||||
|
|
||||||
(** [t] generated by the OCaml code. The first argument should be
|
(** [t] generated by the OCaml code. The first argument should be
|
||||||
[__POS__]. The second is either a string to parse, a variable name
|
[__POS__]. The second is either a string to parse, a variable name
|
||||||
or plain text. [quoted] says whether the string is quoted ([false]
|
or plain text. [quoted] says whether the string is quoted ([false]
|
||||||
by default). *)
|
by default). *)
|
||||||
val virt : ?quoted: bool -> (string * int * int * int) -> string -> t
|
val virt : ?quoted: bool -> (string * int * int * int) -> string -> t
|
||||||
val virt_var : ?quoted: bool -> (string * int * int * int) -> string -> t
|
val virt_var : ?quoted: bool -> (string * int * int * int) -> string -> t
|
||||||
val virt_text : (string * int * int * int) -> string -> t
|
val virt_text : (string * int * int * int) -> string -> t
|
||||||
|
@ -37,11 +37,11 @@ val vars : t -> String.Set.t
|
||||||
|
|
||||||
val fold : t -> init:'a -> f:('a -> Loc.t -> string -> 'a) -> 'a
|
val fold : t -> init:'a -> f:('a -> Loc.t -> string -> 'a) -> 'a
|
||||||
(** [fold t ~init ~f] fold [f] on all variables of [t], the text
|
(** [fold t ~init ~f] fold [f] on all variables of [t], the text
|
||||||
portions being ignored. *)
|
portions being ignored. *)
|
||||||
|
|
||||||
val iter : t -> f:(Loc.t -> string -> unit) -> unit
|
val iter : t -> f:(Loc.t -> string -> unit) -> unit
|
||||||
(** [iter t ~f] iterates [f] over all variables of [t], the text
|
(** [iter t ~f] iterates [f] over all variables of [t], the text
|
||||||
portions being ignored. *)
|
portions being ignored. *)
|
||||||
|
|
||||||
val is_var : t -> name:string -> bool
|
val is_var : t -> name:string -> bool
|
||||||
|
|
||||||
|
@ -51,42 +51,61 @@ module type EXPANSION = sig
|
||||||
|
|
||||||
val is_multivalued : t -> bool
|
val is_multivalued : t -> bool
|
||||||
(** Report whether the value is a multivalued one (such as for
|
(** Report whether the value is a multivalued one (such as for
|
||||||
example ${@}) which much be in quoted strings to be concatenated
|
example ${@}) which much be in quoted strings to be concatenated
|
||||||
to text or other variables. *)
|
to text or other variables. *)
|
||||||
|
|
||||||
type context
|
type context
|
||||||
(** Context needed to expand values of type [t] to strings. *)
|
(** Context needed to expand values of type [t] to strings. *)
|
||||||
|
|
||||||
val to_string : context -> t -> string
|
val to_string : context -> t -> string
|
||||||
(** When needing to expand with text portions or if the
|
(** When needing to expand with text portions or if the
|
||||||
string-with-vars is quoted, the value is converted to a string
|
string-with-vars is quoted, the value is converted to a string
|
||||||
using [to_string]. *)
|
using [to_string]. *)
|
||||||
|
end
|
||||||
|
|
||||||
|
module Expand : sig
|
||||||
|
module Full : sig
|
||||||
|
type nonrec 'a t =
|
||||||
|
| Expansion of 'a
|
||||||
|
| String of string
|
||||||
|
end
|
||||||
|
module Partial : sig
|
||||||
|
type nonrec 'a t =
|
||||||
|
| Expansion of 'a
|
||||||
|
| String of string
|
||||||
|
| Unexpanded of t
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
module Expand_to(V : EXPANSION) : sig
|
module Expand_to(V : EXPANSION) : sig
|
||||||
val expand : V.context -> t -> f:(Loc.t -> string -> V.t option) ->
|
val expand
|
||||||
(V.t, string) Either.t
|
: V.context
|
||||||
|
-> t
|
||||||
|
-> f:(Loc.t -> string -> V.t option)
|
||||||
|
-> V.t Expand.Full.t
|
||||||
(** [expand t ~f] return [t] where all variables have been expanded
|
(** [expand t ~f] return [t] where all variables have been expanded
|
||||||
using [f]. If [f loc var] return [Some x], the variable [var] is
|
using [f]. If [f loc var] return [Some x], the variable [var] is
|
||||||
replaced by [x]; otherwise, the variable is inserted as [${var}]
|
replaced by [x]; otherwise, the variable is inserted using the syntax
|
||||||
or [$(var)] — depending on the original concrete syntax used. *)
|
it was originally defined with: ${..} or $(..) *)
|
||||||
|
|
||||||
val partial_expand :
|
val partial_expand
|
||||||
V.context -> t -> f:(Loc.t -> string -> V.t option) ->
|
: V.context
|
||||||
((V.t, string) either, t) Either.t
|
-> t
|
||||||
(** [partial_expand t ~f] is like [expand_generic] where all
|
-> f:(Loc.t -> string -> V.t option)
|
||||||
variables that could be expanded (i.e., those for which [f]
|
-> V.t Expand.Partial.t
|
||||||
returns [Some _]) are. If all the variables of [t] were
|
(** [partial_expand t ~f] is like [expand_generic] where all
|
||||||
expanded, a string is returned. If [f] returns [None] on at
|
variables that could be expanded (i.e., those for which [f]
|
||||||
least a variable of [t], it returns a string-with-vars. *)
|
returns [Some _]) are. If all the variables of [t] were
|
||||||
|
expanded, a string is returned. If [f] returns [None] on at
|
||||||
|
least a variable of [t], it returns a string-with-vars. *)
|
||||||
end
|
end
|
||||||
|
|
||||||
val expand :
|
val expand :
|
||||||
t -> f:(Loc.t -> string -> string option) -> string
|
t -> f:(Loc.t -> string -> string option) -> string
|
||||||
(** Specialized version [Expand_to.expand] that returns a string (so
|
(** Specialized version [Expand_to.expand] that returns a string (so
|
||||||
variables are assumed to expand to a single value). *)
|
variables are assumed to expand to a single value). *)
|
||||||
|
|
||||||
val partial_expand :
|
val partial_expand :
|
||||||
t -> f:(Loc.t -> string -> string option) -> (string, t) Either.t
|
t -> f:(Loc.t -> string -> string option) -> (string, t) Either.t
|
||||||
(** [partial_expand] is a specialized version of
|
(** [partial_expand] is a specialized version of
|
||||||
[Expand_to.partial_expand] that returns a string. *)
|
[Expand_to.partial_expand] that returns a string. *)
|
||||||
|
|
Loading…
Reference in New Issue