diff options
Diffstat (limited to 'edify/README.md')
-rw-r--r-- | edify/README.md | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/edify/README.md b/edify/README.md new file mode 100644 index 000000000..b3330e23a --- /dev/null +++ b/edify/README.md @@ -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()) |