Module Excmd.AST
Describing structures
Some of our data-structures provide conversion functions to produce alternative formats of themselves. These are automatically generated at compile-time by PPX preprocessors in OCaml.
Unfortunately, we use different data-structures per compile-target: in native OCaml, we use {{:https://github.com/ocaml-ppx/ppx_deriving_yojson} ppx_deriving_yojson}
to produce a value of type Yojson.Basic.json
; but when being compiled to JavaScript, we use BuckleScript's jsConverter
tooling to generate the built-in Js.t
type. These generators also produce functions of different names: to_yojson
is available on the native side, and tToJs
on the BuckleScript side.
Due to the fact that the relevant types differ between platforms, fully generic code involving alternative-format representations like the above isn't clean and easy. Both of the above flavours of conversion-function will raise a runtime exception if called on a platform that doesn't support them; if you need to, you can catch said exception and swap implementations based on that.
val tOfJs : 'a -> 'b
val tToJs : 'a -> 'b
val expressionOfJs : 'a -> 'b
val expressionToJs : 'a -> 'b
val to_yojson : 'a -> 'b
val of_yojson : 'a -> 'b
val expression_to_yojson : 'a -> 'b
val expression_of_yojson : 'a -> 'b
type 'a unresolved
=
|
Unresolved
|
Resolved of 'a
|
Absent
This triple extends the usual
option
al type with an intermediateUnresolved
state. It's used inflag
s to indicate the presence of a subsequentPositional
argument that may-or-may-not be thepayload
of saidflag
.
val unresolved_to_yojson : a. ('a -> Yojson.Safe.json) -> 'a unresolved -> Yojson.Safe.json
type 'a or_subexpr
=
|
Sub of expression
|
Literal of 'a
Wraps any value that may be replaced in the AST by a subexpression; i.e., in the expression
echo hello world
the literalhello
will be wrapped inLiteral
. This is necessary because it could just as easily beecho (echo hello) world
.
type word
= string or_subexpr list
The most granular element of an excmd, like a shell command, is the "word." These are a series of parameters to a command, separated by whitespace:
echo each of these is a separate "word"
Words can also be produced by subexpressions,
echo each of these is a (echo separate) "word"
... or created via quotation:
echo "this is only a single word"
A single shell "word" can actually be composed of multiple quotations or subexpressions, as long as they are not separated by whitespace:
echo "this""is""only""a""single"(echo word)(echo also)
Such a composition is represented in this type, by a series of
or_subexpr
s in alist
.
type flag
=
{
name : string;
mutable payload : word unresolved;
}
A single
--flag
, possible with-a=payload
. The flag's name is always literal; but the payload may be:cmd --fl="a quotation,"
cmd --fl=(echo a subexpression)
cmd --fl=or"a"(echo smooshing)"thereof"
(Although this type is technically mutable, it's probably a better idea to leave the mutation up to the
Expression
-interface.)
type arg
=
|
Positional of word
|
Flag of flag
type expression
=
{
count : int;
cmd : word;
mutable rev_args : arg list;
}
val or_subexpr_to_yojson : a. ('a -> Yojson.Safe.json) -> 'a or_subexpr -> Yojson.Safe.json
val word_to_yojson : word -> Yojson.Safe.json
val flag_to_yojson : flag -> Yojson.Safe.json
val arg_to_yojson : arg -> Yojson.Safe.json
val expression_to_yojson : expression -> Yojson.Safe.json
type t
=
{
expressions : expression array;
}
val to_yojson : t -> Yojson.Safe.json
val make_expression : ?count:string -> cmd:word -> rev_args:arg list -> expression
val pipe_last : from:expression -> into:expression -> expression
val copy_word : word -> word
val copy_flag : flag -> flag
val copy_arg : arg -> arg
val copy_expression : expression -> expression
val copy : t -> t
val pp_bs : 'a -> 'b
val pp_native : t -> unit
val pp : t -> unit
val pp_expression_bs : 'a -> 'b
val pp_expression_native : expression -> unit
val pp_expression : expression -> unit
val is_literal : 'a or_subexpr -> bool
val get_literal_exn : 'a or_subexpr -> 'a
val get_sub_exn : 'a or_subexpr -> expression