```(** Constant folding
*
* These routines provide constant folding.  Felix recognizes plain integers,
* strings, and boolean values as constants, and folds expressions involving
* all the basic operations on them as follows:
*
* {[
* // integers
* -x, neg x
* +x, pos x
* abs x
* x-y, sub(x,y)
* x*y, mul(x,y)
* x/y, div(x,y)
* x % y, mod(x,y)
* x ** y, pow(x,y)
* xy, gt(x,y)
* x<=y, le(x,y)
* x>=y, ge(x,y)
* x=y, eq(x,y)
* x!=y, x<>y,ne(x,y)

* // strings
* x*n, mul(x,n) // concatenate n copies of x
* x=y, eq(x,y)
* x!=y, x<>y,ne(x,y)
* x n // append the utf8 encoding of n to x
* x y // same as x + y

* // ustrings
* x*n, mul(x,n) // concatenate n copies of x
* x=y, eq(x,y)
* x!=y, x<>y,ne(x,y)
* x n // append the char of code value n to x

* // bool
* not x, lnot(x,y)
* x or y, lor(x,y)
* x and y, land(x,y)
* x=y, eq(x,y)
* x!=y, x<>y,ne(x,y)

* // conditional
* if c then e1 else e2 endif // compile time shortcut
* ]}
*
* Note the conditional fold, which replaces the conditional with either e1 or
* e2 if c is a boolean constant expression.
*
* Note the string formation forms:
*
* {[
* "" 27 987
* u"" 27 987
* ]}
*
* have the same ISO-10646 interpretation, however the first string is 8 bit,
* and the 987 is replaced by its UTF-8 encoding, whilst the second string is
* 32 bit, and the integral value is represented directly.
*
* Implementation note: both string types are represented internally by 8 bit
* UTF-8 encoded strings.
**)

open Flx_ast
val const_fold:
expr_t -> expr_t
```