How Mathematical Formulas can be Organized for Literate Programming

I have come to believe that the use of mathematical notations for programming screams for the adoption of Donald Knuth's "literate programming". Instead of writing source files of mathematical formulas, one should simply write a document that describes an algorithm but also serves as its executable implementation. Below I describe a technique for organizing formulas in a way that makes literate programming feasible with mathematical notation instead of code.

In my 2007 Introduction to Caltha, I gave the following implementation of a root-finding algorithm. The idea was to define the algorithm using mathematical notations, as one might do on paper or in a lecture. But because the mathematical definition is complete, it could be executed by a computer as well.
the original root finding algorithm
The key to the Caltha Programming Language, as it existed at the time, was the fact that multiple statements could be placed inside a single pair of parentheses. Note that in the formula above, if r > h, then three statements are executed: the assignment y:= f(x), the update of x and r, and the recursive invocation of root. I no longer like this notation, however, for the simple reason that the resulting formulas become too large.

The problem with large formulas is that they are difficult to describe. One solution would be to insert comments into a large formula, as one inserts comments into a large block of code. But this of course would make the formula even larger. A better approach is to partition the large formula into several small formulas, as Knuth would partition a large block of code into several small blocks of code. Observe, for example, this new implementation of the root-finding algorithm.
the new root finding algorithm
The algorithm itself has not changed, though we now have three small formulas instead of one large one. Note that the lower two formulas are indented. The indentation affects the scope of each variable. It ensures, for example, that the arguments of root can be used in the definition of x', r', and y. The indentation also ensures that x', r', and y will be re-evaluated each time root is re-evaluated.

Now that we have several small formulas, we may present them in alternation with text.
The function root approximates the root of its argument function f. The initial guess x must be within a distance r of the actual root, and we assume that f is increasing in the interval between x - r and x + r. The result of root is the final approximation, which will be within a distance h of the actual root. As shown below, if r is at most h, then x is the final approximation. Otherwise, root is evaluated recursively with an updated guess x' and an updated distance r'.
definition of root

The updated guess x' and an updated distance r' are calculated as follows. If f(x) is zero, then x is the root and we can define r' as 0. If f(x) is positive or negative, we can define x' as x translated by r/2 in the appropriate direction. In that case r' is r/2.
definition of x' and r'
Note that when the definition of root is separated from the definition of x' and r', the indentation is lost. This is why we must add the context identifier <<root>> to the second formula. We could separate y:= f(x) as well, if we wanted to, in which case we would give it the context identifier <<root; [x', r']>> (or <<...; [x', r']>>, with "..." meaning "the context of the previous formula").

The convention that I propose, using indentation and context identifiers, would make literate programming practical with mathematical notation instead of code. Documents created with this system would resemble the papers that present-day algorithm designers already write, with the added benefit that the new documents could be executed by a computer.