Greg Ewing wrote:
> Dag Sverre Seljebotn wrote:
>
>> Because LetNodes can be introduced after what is currently the
>> allocate_temps phase, the allocate_temps phase must then be moved (if we
>> keep it; I'm basically saying "turn it into a pre-generation transform).
>
> One of the undesirable things about the current scheme is that
> there is a subtle coupling between the temp allocation and
> code generation phase. Not only is it a source of error when
> modifying things, it also leads to some bizarre-looking
> code in the allocate_temps phase, such as allocating a temp
> and then immediately releasing it, which looks redundant,
> but is actually necessary.
>
> Simply moving the allocate_temps phase to a different place
> wouldn't do anything to remove the dependency. If it's folded
> into the code generation phase, however, the general patter

Yes, this is what I was worried about (and explained rather poorly, and I
made some wrong assumptions about your proposal as well, so I won't
attempt to clean up the parts where I was unclear).

> would become
>
>    1. Generate code to evaluate subexpressions.
>    2. Allocate temp for the result of this node if needed.
>    3. Generate code to calculate result based on results
>       of subexpressions.
>    4. Release temps holding results of subexpressions.
>
> which actually makes sense.

5. Dispose result temp when parent calls generate_disposal_code? (For the
record and checking of understanding).

Great!, I'm +1 now -- integrating temp allocation with C code generation
makes it very easy to get the most optimal temp usage possible.

Also, this can also be implemented without affecting existing code --
simply have Code.py (and FuncDefNode) support these new temps in addition
(with another prefix perhaps), then move on to slowly migrating existing
code as-needed. And once that is done it is much easier to move the
result_code generation of temporary exprnodes.

(Note: Yes, the nested subexpression unrolling was a particularily silly
one. And it definitely should not happen for C code.)

> Note that for most expression nodes, most of this pattern
> could be implemented by a general method in ExprNode which
> calls a node-specific method to implement (3) (as is done now,
> except it's split between the temp allocation and code
> generation phases).
>
>> - During analysis/transformation, you know "what you are doing" and how
>> many temps you will need.
>
> I'm not convinced you really need to know about temps during
> analysis. To my mind, temps are analogous to registers in a
> conventional compiler -- something very low-level that you
> only deal with late in the pipeline. Tree transformations
> should operate at a higher level of abstraction.
>
> The abstraction I would choose is "extra local variable",
> which is what the LocalNode represents. Whether it uses
> the same mechanism as that for the intermediate results of
> expressions is an implementation detail, as is whether it
> makes use of an Entry in the symbol table.

Yes, these turn orthogonal things and the interface of LetNode
functionality doesn't depend on how temps are done.

Shifting over to LetNode; during analyse_declarations stuff like
CVarDeclNode (and probably CArgDeclNode etc. when we get around to it) is
stripped from the tree and no longer considered in the transforms, as the
information has been moved over to the scope. So to be consistent with
this one could think that LetNode should have a LocalNode prior to
analyse_declarations; and after that it would have entries, as that is how
other variables work (not necesarrily registered in a scope; if they were,
one would have to create a new LetScope etc. which is kind of a pain).

Note that after analyse_declarations, transforms have to (and currently
does) modify the scopes directly to do their stuff with variables. (For
this purpose, ModuleNode and FuncDefNode has scope and local_scope
variables added that can be followed by transforms and inspected and
modified).

I suppose LetNode should be left until there is a temp system available
that let one generate. I may very well end up supporting your approach in
a few days.

> I'm expecting that various things such as for-loops will
> be implementable using LetNodes with suitable internal
> plumbing, so the custom nodes for these statements would
> disappear, along with the custom code in them implementing
> the temp allocation and code generation patterns. That's
> an increase in re-use, to my way of thinking.

Indeed (me and Robert just discussed this in the other current thread,
though without the needed LetNode principle).

>> Entry seems like a more natural concept for this to me -- because it is
>> a
>> more "refined", more basic concept of a handle to a variable in the
>> scope.
>
> I don't see what you gain by doing this. Under my
> proposal, there would only be one kind of thing for tree
> transformations to deal with, i.e. Nodes. Under yours,
> there would be two kinds of things -- Nodes and Entries.

Already talked about this some...just wanted to give another example: I
recently wanted to do something at the beginning of the function for each
argument of a certain type -- my transform then iterated the
funcdefnode.local_scope.arg_entries, and added its statements to the
beginning of funcdefnode.body. In transforms look at Scope and Entry
somewhat like a fancy dictionary which the function or module use for
storing information about themselves (although it is at the same time a
parallel tree following namespace nesting rather than code structure
nesting...)

But -- if treating LetNode-level-temps (as opposed to
C-"register"-level-temps) as Entries only adds overhead and no benefits I
will let go of the idea...

I think it is mostly the CloneNode that scares me, that doesn't look very
intuitive to use from a transform perspective.

>> Unless you cache the function bodies it would need to be done right
>> prior,
>> so that you know which local variables to declare.
>
> I would split the code stream for the function body
> in two, one for the declarations and one for the statements.
> That wouldn't be hard to do -- I'm already doing something
> similar with the module-level declarations (the 'h'
> attribute of the code object refers to another code
> object that collects the declarations in a StringIO).

Excellent.

Dag Sverre

_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to