1edify
2=====
3
4Update scripts (from donut onwards) are written in a new little
5scripting language ("edify") that is superficially somewhat similar to
6the old one ("amend").  This is a brief overview of the new language.
7
8- The entire script is a single expression.
9
10- All expressions are string-valued.
11
12- String literals appear in double quotes.  \n, \t, \", and \\ are
13  understood, as are hexadecimal escapes like \x4a.
14
15- String literals consisting of only letters, numbers, colons,
16  underscores, slashes, and periods don't need to be in double quotes.
17
18- The following words are reserved:
19
20       if    then    else   endif
21
22  They have special meaning when unquoted.  (In quotes, they are just
23  string literals.)
24
25- When used as a boolean, the empty string is "false" and all other
26  strings are "true".
27
28- All functions are actually macros (in the Lisp sense); the body of
29  the function can control which (if any) of the arguments are
30  evaluated.  This means that functions can act as control
31  structures.
32
33- Operators (like "&&" and "||") are just syntactic sugar for builtin
34  functions, so they can act as control structures as well.
35
36- ";" is a binary operator; evaluating it just means to first evaluate
37  the left side, then the right.  It can also appear after any
38  expression.
39
40- Comments start with "#" and run to the end of the line.
41
42
43
44Some examples:
45
46- There's no distinction between quoted and unquoted strings; the
47  quotes are only needed if you want characters like whitespace to
48  appear in the string.  The following expressions all evaluate to the
49  same string.
50
51     "a b"
52     a + " " + b
53     "a" + " " + "b"
54     "a\x20b"
55     a + "\x20b"
56     concat(a, " ", "b")
57     "concat"(a, " ", "b")
58
59  As shown in the last example, function names are just strings,
60  too.  They must be string *literals*, however.  This is not legal:
61
62     ("con" + "cat")(a, " ", b)         # syntax error!
63
64
65- The ifelse() builtin takes three arguments:  it evaluates exactly
66  one of the second and third, depending on whether the first one is
67  true.  There is also some syntactic sugar to make expressions that
68  look like if/else statements:
69
70     # these are all equivalent
71     ifelse(something(), "yes", "no")
72     if something() then yes else no endif
73     if something() then "yes" else "no" endif
74
75  The else part is optional.
76
77     if something() then "yes" endif    # if something() is false,
78                                        # evaluates to false
79
80     ifelse(condition(), "", abort())   # abort() only called if
81                                        # condition() is false
82
83  The last example is equivalent to:
84
85     assert(condition())
86
87
88- The && and || operators can be used similarly; they evaluate their
89  second argument only if it's needed to determine the truth of the
90  expression.  Their value is the value of the last-evaluated
91  argument:
92
93     file_exists("/data/system/bad") && delete("/data/system/bad")
94
95     file_exists("/data/system/missing") || create("/data/system/missing")
96
97     get_it() || "xxx"     # returns value of get_it() if that value is
98                           # true, otherwise returns "xxx"
99
100
101- The purpose of ";" is to simulate imperative statements, of course,
102  but the operator can be used anywhere.  Its value is the value of
103  its right side:
104
105     concat(a;b;c, d, e;f)     # evaluates to "cdf"
106
107  A more useful example might be something like:
108
109     ifelse(condition(),
110            (first_step(); second_step();),   # second ; is optional
111            alternative_procedure())
112