Florian Klaempfl schrieb:

I stopped searching after finding such code in aasmtai, aoptbase,
aoptobj, assemble, globals, nadd, ncgutil, nld, ogcoff, options,
optloop, pdecsub, pmodules, psub, symdef, systems.

Well, I see no problem with it. Of course, one can do an overly complex
design to avoid this but as I said before, I see no use in doing so. It
makes only maintainance more complex.

That's why I suggested solutions other than $IFDEF or virtual methods.

Many $IFDEFs also occur in declarations and uses clauses. These parts should be removed from the general compiler code, with all such details encapsulated in the back-end class(es).


For logical (functional) grouping. Looking at the parser, a single unit
would be sufficient for every front-end.

This is not logical to me. For me it is logical to group the parser by
expression sub parser, declaration sub parser etc. and even split the
declaration parser into type etc. one.

A parser structure should support the maintenance of the language, i.e. syntax. In so far I'd group together e.g. directive handling, to ease the maintenance in case of new directives. Your suggested structure applies to the semantics of the language, which should be implemented outside a concrete parser (front-end). It's also a bad idea to move procedure processing into a different class (tprocinfo), and let it call paser methods from there. That's turning things upside down, breaking the recommended separation between front-ends and compiler :-(

In an OO design the parser methods must reside in one class, so that the means for further structuring are very limited. That's why I suggested local subroutines for parsing specific (non-reusable) parts of the language.


so that finally the compiler could be decomposed into a
small number of building blocks (packages...), with tiny interfaces to
each other.
Counter example: your attempt of the OOP parser :)
What's wrong with the parser interface in TParser?

That it inherits from TScanner.

It's only a matter of taste, whether the parser should be a member or the base of the parser class. My choice of a base class allows to hide many methods and fields from the public scanner interface, that shall be used only by the parser. A member also introduces another reference (indirection), and another (global) variable, so I decided to inherit from the scanner class.

The next decision, of turning the parser units into include files, is also only an intermediate step. When the semantics have been separated from the parser, the code in these include files can be moved into the language unit, and the remaining p* units will contain nothing but the semantical interface to the intermediate data structures. *That* is the place where your suggested structure makes sense, no doubt :-)



A formal separation of cpubase from cpuinfo is not helpful, unless it
has a logical (functional) justification.


It has for me a logical and formal one: cpuinfo contains info which is
used by generic/common parts of the compiler. Cpubase contains the basic
stuff which is used by the cpu specific part of the compiler. Of course,
there are deviations from this rule due to laziness and simplicity and
refactoring over time, but this is how it is used to be.

Thanks, I'll remember that for a later later refactoring. In my attempt to unify the existing back-ends, I came across several abstract classes (tai...), which look like the more "natural" candidates for back-end base classes. When the cpubase (and more) information and procedures are moved into the interface of these classes, unwanted references to concrete cpu units can no more occur in both the compiler and external tools.

DoDi

_______________________________________________
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply via email to