Am 13.07.2019 um 14:12 schrieb J. Gareth Moreton:
I would like some discussion on this with the administrative team
because this does require some careful design if we're going to do
this properly. Building on Florian's suggestion, I would like to
propose splitting "pass_1" into "pass_syntax" and a pass that
transforms the nodes (I would name it "pass_transform", but this
doesn't sound 'important' enough, given it is effectively compiling
the nodes). "pass_syntax" would be a public method declared in tnode
as the following "function pass_syntax: Boolean; virtual;" - if it
returns True, then everything was fine; if not, it returns False and
this can be used to set the error flag. By being defined this way,
this is no ability for the node to transform itself, but it can set
private fields based on the syntax it finds (by setting private
fields, the "first pass" won't have to repeat some of the work needed
to determine how to transform the nodes).
"pass_syntax" is not a good name, because it does *not* do syntax
checking (that was done by the parser). Instead it checks the semantic,
so "pass_semantic" would be a more correct name.
Also I don't think a Boolean result is needed. Take a look at
tgotonode.pass_1 which is after all the one which would need to be moved
to pass_semantic: it uses CGMessage*() to write its messages (as all
nodes do) which in turn sets the codegenerror flag if it wasn't set
already. So after a call to a node's pass_semantic method all that needs
to be checked is codegenerror to decide how to proceed further. Thus the
semantic pass could simply be "procedure pass_semantic;virtual;".
On the surface, the first implementation suggestion feels like the
cleaner option, but I don't know how much of a penalty it will add to
the compiler. Personally I would like to attempt a design for the
second implementation to keep the number of passes down to a minimum
and the compiler reasonably fast (also my motivation behind the x86_64
peephole optimizer overhaul). But that's just my opinion.
In my opinion a clean, easily maintainable solution is preferrable.
On an additional note, I do wonder if it's possible to merge "pass_1"
and "simplify", since they are treated pretty much identically in the
"firstpass" routine - if either of them return something other than
nil, it is considered to be a node transformation, running this block
of code (there are two copies, one for each call):
p.free;
p := hp;
firstpass(p);
(hp contains the return value of whatever method was just called) This
may be impractical because "simplify" is called elsewhere for some nodes.
I don't think combining the two passes is necessary. The ideas behind
the two passes are after all different.
Regards,
Sven
_______________________________________________
fpc-devel maillist - fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel