Executive Summary
x.gen_blocks generates a tree of nested blocks. Instead, it might create a list of sequential blocks.
This new scheme greatly simplifies complex code, but several new and old problems must be resolved.
Background
This thread started the train of thought.
i.preprocess_blocks moves lines between blocks just by incrementing two ints! As a result, my attention rested on the
i.Block class.
I had forgotten that
x.gen_blocks generates a tree of nested blocks. This seemed unnecessarily clumsy. After all, the key invariant is that blocks must cover the source code without gaps.
What was going on? Well, I was focused on accuracy above
simplicity. But the resultant complexity obscured possible
simplifications.
The Aha!
Generating nested blocks is tricky, as you can see from the base i.gen_block method. Furthermore, i.gen_block relies on i.find_blocks, another complex method! Worse, the overridden python_i.find_blocks is truly hairy.
Why did I choose this approach? Because it allows all importers to know the end of each block. You would think this would be essential information!
But Aha! Suppose each block ends with the start of the next block? At first glance, this would be a perfect solution!
Finding blocks becomes much more straightforward. See the experimental(!) version of python_i.gen_block in PR
#4422. This version replaces the (complex!) legacy helpers (
python_i.find_blocks and
python_i.find_end_of_block) with the much simpler
python_i.find_start_of_body.
But the new scheme won't work immediately. Blocks representing classes will end with their first method! Such blocks will be equivalent (in some ill-defined sense) to:
class MyClass...:
<preamble> # Everything before the first method.
@others
This won't do. We must generate something like this:
class MyClass...:
<preamble>
@others
<postamble> # Anything following the last method.
Finally,
let's discuss underindented lines. This is an existing problem that
can't be solved in a truly satisfactory way because Leo no longer has a
way of representing underindented lines. Leo's legacy importers handle
such lines by generating code like this:
class MyClass...:
<preamble>
@others
<postamble>
The relevant code is buried deep in the weeds.
Imo, the new importers must handle underindented lines in the same way.
Summary
Using a list of sequential (non-nested) blocks promises to simplify all importers, not just the Python importer.
However, the PR is highly experimental. Complications may appear. We'll see how this scheme pans out.
Edward