Module Excmd.Expression
type tAn alias to
AST.expression, abstracted that mutation may be controlled.
type flag_payload=|Empty|Payload of AST.word
Basic getters
val count : t -> intval command : t -> AST.wordval mem : string -> t -> boolmem fl exprreturnstrueifexprcontains flagfl,falseotherwise.Notably, this does not resolve any unresolved words from the parsed expression.
val is_resolved : string -> t -> boolis_resolved fl exprreturnstrueifexprcontains a flagfland the last such flagflis already resolved; andfalseotherwise.
val has_payload : string -> t -> boolhas_payload fl exprreturnstrueifexprcontains a flagfl, the last such flagflis already resolved, and that last flagflresolved to astringpayload instead of abool. Returnsfalseotherwise.
val flags : t -> string listflags exprreturns a list of the flags used inexpr, including only the names of flags - not the payloads.
Resolvers (mutative getters)
val positionals : t -> AST.word listpositionals exprreturns alistof positional (non-flag) arguments inexpr.This fully resolves
expr— any ambiguous words will be consumed as positional arguments, becoming unavailable as flag-payloads.
val iter : (string -> flag_payload -> unit) -> t -> unititer f exprappliesfto all flags in expressionexpr.freceives the flag as its first argument, and the associated, fully-resolved value as the second argument.This fully resolves
expr— any ambiguous words will be consumed as the values to their associated flags, becoming unavailable as positional arguments.
val iteri : (int -> string -> flag_payload -> unit) -> t -> unititeri f expr, as withiter, appliesfto each flag inexpr. However,fwill also receive the index of each flag as an argument.
val rev_iteri : (int -> string -> flag_payload -> unit) -> t -> unitrev_iteri f expr, as withiteri, appliesfto each flag inexpr; except that the flags are observed in reverse order — from the end of the expression, to the start. (This is marginally more efficient than eitheriteroriteri.)
val flag : string -> t -> flag_payload optionflag fl exprfinds a flag by the name offl, resolves it if necessary, and produces the payload there of, if any.This can yield ...
None, indicating flagflwas not present at all.Some Empty, indicating a flagflwas present, but the last such resolved to having no payload.Some (Payload word), indicating a flagflwas present and the last such became resolved to the payloadword. This can involve resolution of the word immediately following saidfl, removing it from the implicitpositionals.
Other helpers
val pp : t -> unitPretty-print a expression. Implementation varies between platforms.
val hydrate : t -> AST.expressionType-converter between abstract
Expression.tand concreteAST.expression.Careful; the operations in this module are intended to maintain safe invariants, consuming components of a
expressionin reasonable ways. You must not devolve one into a rawASTnode, modify it unsafely, and then expect to continue to use the functions in this module.
Note: Resolution of ambiguous words
It's important to note that a expression is a mutable structure, and that accesses intentionally mutate that structure — in particular, a given word in the original parsed string can only be either a positional argument or the argument to a preceding flag.
Any function that accesses either the value of a flag, or accesses the positionals at all, is going to “resolve” that word in the original source. If the word was ambiguously positioned, that access will result in the datastructure changing — to prevent the word later becoming resolved in an incompatible way.
For example: given the following input command as a Expression.t,
hello -- where world ... there's two possible ways to interpret the 'world', chosen between by the order in which you invoke either positionals, or flag-value-reading functions (like iter or find/flag):
(* Yields zero positionals, and 'world' as the value associated with the flag '--where'. *)
let expr1 = Parser.expression_of_string "hello --where world" in
let where = Expression.flag "where" expr1 (* Some (Payload 'world') *) in
let xs = Expression.positionals expr1 (* [] *)
(* Yields one positional, 'world', and no value associated with the flag '--where'. *)
let expr2 = Parser.expression_of_string "hello --where world" in
let xs = Expression.positionals expr2 (* ['world'] *) in
let where = Expression.flag "where" expr2 (* Some (Empty) *)Once any ambiguous words have been so resolved (or when a function is called that inherently resolves all ambiguous words, such as positionals or iter), a Expression.t is considered “fully resolved.” No functions in this module will further mutate such a expression.