edify: Some clean-ups to libedify.
- Remove dead declarations in expr.h: SetError(), GetError(), ClearError(). - Remove the declaration of Build() out of expr.h. - Use std::unordered_map to implement RegisterFunction() and FindFunction(); kill FinishRegistration(). - Add a testcase for calling unknown functions. Test: mmma bootable/recovery; recovery_component_test passes. Change-Id: I9af6825ae677f92b22d716a4a5682f58522af03b
This commit is contained in:
+111
@@ -0,0 +1,111 @@
|
||||
edify
|
||||
=====
|
||||
|
||||
Update scripts (from donut onwards) are written in a new little
|
||||
scripting language ("edify") that is superficially somewhat similar to
|
||||
the old one ("amend"). This is a brief overview of the new language.
|
||||
|
||||
- The entire script is a single expression.
|
||||
|
||||
- All expressions are string-valued.
|
||||
|
||||
- String literals appear in double quotes. \n, \t, \", and \\ are
|
||||
understood, as are hexadecimal escapes like \x4a.
|
||||
|
||||
- String literals consisting of only letters, numbers, colons,
|
||||
underscores, slashes, and periods don't need to be in double quotes.
|
||||
|
||||
- The following words are reserved:
|
||||
|
||||
if then else endif
|
||||
|
||||
They have special meaning when unquoted. (In quotes, they are just
|
||||
string literals.)
|
||||
|
||||
- When used as a boolean, the empty string is "false" and all other
|
||||
strings are "true".
|
||||
|
||||
- All functions are actually macros (in the Lisp sense); the body of
|
||||
the function can control which (if any) of the arguments are
|
||||
evaluated. This means that functions can act as control
|
||||
structures.
|
||||
|
||||
- Operators (like "&&" and "||") are just syntactic sugar for builtin
|
||||
functions, so they can act as control structures as well.
|
||||
|
||||
- ";" is a binary operator; evaluating it just means to first evaluate
|
||||
the left side, then the right. It can also appear after any
|
||||
expression.
|
||||
|
||||
- Comments start with "#" and run to the end of the line.
|
||||
|
||||
|
||||
|
||||
Some examples:
|
||||
|
||||
- There's no distinction between quoted and unquoted strings; the
|
||||
quotes are only needed if you want characters like whitespace to
|
||||
appear in the string. The following expressions all evaluate to the
|
||||
same string.
|
||||
|
||||
"a b"
|
||||
a + " " + b
|
||||
"a" + " " + "b"
|
||||
"a\x20b"
|
||||
a + "\x20b"
|
||||
concat(a, " ", "b")
|
||||
"concat"(a, " ", "b")
|
||||
|
||||
As shown in the last example, function names are just strings,
|
||||
too. They must be string *literals*, however. This is not legal:
|
||||
|
||||
("con" + "cat")(a, " ", b) # syntax error!
|
||||
|
||||
|
||||
- The ifelse() builtin takes three arguments: it evaluates exactly
|
||||
one of the second and third, depending on whether the first one is
|
||||
true. There is also some syntactic sugar to make expressions that
|
||||
look like if/else statements:
|
||||
|
||||
# these are all equivalent
|
||||
ifelse(something(), "yes", "no")
|
||||
if something() then yes else no endif
|
||||
if something() then "yes" else "no" endif
|
||||
|
||||
The else part is optional.
|
||||
|
||||
if something() then "yes" endif # if something() is false,
|
||||
# evaluates to false
|
||||
|
||||
ifelse(condition(), "", abort()) # abort() only called if
|
||||
# condition() is false
|
||||
|
||||
The last example is equivalent to:
|
||||
|
||||
assert(condition())
|
||||
|
||||
|
||||
- The && and || operators can be used similarly; they evaluate their
|
||||
second argument only if it's needed to determine the truth of the
|
||||
expression. Their value is the value of the last-evaluated
|
||||
argument:
|
||||
|
||||
file_exists("/data/system/bad") && delete("/data/system/bad")
|
||||
|
||||
file_exists("/data/system/missing") || create("/data/system/missing")
|
||||
|
||||
get_it() || "xxx" # returns value of get_it() if that value is
|
||||
# true, otherwise returns "xxx"
|
||||
|
||||
|
||||
- The purpose of ";" is to simulate imperative statements, of course,
|
||||
but the operator can be used anywhere. Its value is the value of
|
||||
its right side:
|
||||
|
||||
concat(a;b;c, d, e;f) # evaluates to "cdf"
|
||||
|
||||
A more useful example might be something like:
|
||||
|
||||
ifelse(condition(),
|
||||
(first_step(); second_step();), # second ; is optional
|
||||
alternative_procedure())
|
||||
Reference in New Issue
Block a user