o made all (non-abstract) tdef and tsym constructors virtual
o added c*def/c*sym classref types for every (non-abstract) t*def/t*sym
class
o added cpusym unit for every architecture that derives a tcpu*def/tcpu*sym
class from the base classes, and initialises the c*def/c*sym classes with
them. This is done so that the llvm target will be able to derive from
the tcpu*def/sym classes without umpteen ifdefs, and it also means that
the WPO can devirtualise everything because the c* variables are only
initialised with one class type
o replaced all t*def/t*sym constructor calls with c*def/c*sym constructor
calls
git-svn-id: trunk@27361 -
The cause of the internal error was the following:
We have a generic in an unit ("A") which uses another unit ("B") in the implementation section and this other unit uses unit A in the interface section. Now the generic is specialized in the interface section of B. This leads to the problem that in unit A when it tries to load the globalsymtable of unit B that globalsymtable will be Nil, because parsing of the interface section is not yet finished. Thus the change in pgenutil.pas, specialization_init: if the unit is still "in_interface" the localsymtable needs to be used instead of the globalsymtable.
This doesn't necessarily lead to a compiling test though, as there is the following possibility:
Unit A contains a generic class/record (with methods) and uses unit B in the implementation section. This unit B also contains a generic class/record (with methods) and uses unit A in the implementation section. Both units contain a specialization of the other unit's generic outside of it's own generics (such that generate_specialization is fully triggered). Let's assume compilation starts with unit A and we reach the uses of unit B. Now compilation switches to unit B and completes as unit A is already registered and in compilation. The problem now is that the generic in unit A still contains unresolved forward declarations as the implementation section of A was not yet parsed which will lead to "forward declaration not solved" errors (Note: Delphi compiles this).
The solution to this is the following: if a generic is specialized from another unit which is not in state ms_compiled then the unit of the specialization needs to wait for the unit of the generic. So the specialization's unit adds itself into a list of waiting units of the generic's unit. Now inside "proc_unit" we need to check whether this module is waiting for other modules and if so avoid "finishing" the unit (which means generating the methods of the specialization, generating assembler code and ultimately freeing the scanner and PPU). Now when the generic's unit finishes we need to check whether other modules are waiting for it and finish them (of course it's a bit more complicated in reality, but that pretty much sums it up).
+ globstat.pas: Added an unit which handles the saving and restoring of the global state which was originally inside "parser.pas, compile" so that Don't Repeat Yourself (DRY) is respected.
* fmodule.pas, tmodule:
+ add fields to keep track of the units the module is waiting for and which modules are waiting for the module
+ add field for the saved global state (raw pointer to avoid circles)
+ add field for the state which is needed to finish the unit (raw pointer to avoid circles)
+ move the code which was used in "parser.pas, compile" after a module was successfully compiled to the new virtual method "end_of_parsing"
+ fppu.pas, tppumodule.end_of_parsing:
free the ppufile here
* pgenutil.pas:
+ add new procedure "maybe_add_waiting_unit" which adds the specialization's unit to the waiting list of the generic if that unit is not yet compiled
* generate_specialization: call the new function when we add a new (true) specialization
* specialization_init: instead of not adding implementation units at all check whether the unit is still parsing the interface section and add the localsymtable in that case
* pmodules.pas:
* change "proc_unit" to a function which returns "true" if the unit was already finished (no need to wait for other units)
+ move the code from "proc_unit" from "generate_specialization_procs" on to a new procedure "finish_unit" which
* this procedure is either called immediately in "proc_unit" if the unit does not need to wait for other units or from "finish_unit" itself if a unit that is waiting for the given unit does no longer wait for another module (special care is taken in proc_unit to avoid circles)
* parser.pas, compile:
* correctly handle the case if an unit is not finished
* use the new global state functionality from globstat.pas
* pay special attention when calling "set_current_module" (see comment at that call)
+ add tests from 22160
+ add test for above mentioned "diamond" case
git-svn-id: trunk@22452 -
- don't parse '(' token after the type declaration inside the type block
- replace parse of "string<codepage>" to "type AnsiString(codepage)" for delphi compatibility
- fix tests to use "type AnsiString(codepage)"
git-svn-id: trunk@19148 -
+ support for nested procedural variables:
o activate using {$modeswitch nestedprocvars} (compatible with all
regular syntax modes, enabled by default for MacPas mode)
o activating this mode switch changes the way the frame pointer is
passed to nested routines into the same way that Delphi uses (always
passed via the stack, and if necessary removed from the stack by
the caller) -- Todo: possibly also allow using this parameter
passing convention without enabling nested procvars, maybe even
by default in Delphi mode, see mantis #9432
o both global and nested routines can be passed to/assigned to a
nested procvar (and called via them). Note that converting global
*procvars* to nested procvars is intentionally not supported, so
that this functionality can also be implemented via compile-time
generated trampolines if necessary (e.g. for LLVM or CIL backends
as long as they don't support the aforementioned parameter passing
convention)
o a nested procvar can both be declared using a Mac/ISO Pascal style
"inline" type declaration as a parameter type, or as a stand-alone
type (in the latter case, add "is nested" at the end in analogy to
"of object" for method pointers -- note that using variables of
such a type is dangerous, because if you call them once the enclosing
stack frame no longer exists on the stack, the results are
undefined; this is however allowed for Metaware Pascal compatibility)
git-svn-id: trunk@15694 -
rtl: add enumerators to the basic classes
tests: add enumerators test which compiles and work both by fpc and dcc
compiler:
+ start for-in loop implementation: implement for-in loop for types (enumerations and ranges), strings, arrays and sets. todo: perform type checking, optimize array and string loops - use temp for expression, implement for-in loop for classes
test:
+ add a simple test for the 'for-in' loop
compiler: fix string for-in loop. now it uses a temp variable to store string expression result
complier: fix for-in array loop. use a temp variable for the loop expression only if loop is not an open array loop
complier: continue enumerator implementation:
+ add operator enumerator which give an ability to add enumerator for an existent type (for example to override builtin string enumerator)
+ add class enumerator support via delphi compatible GetEnumerator method + enumerator class/object template (function MoveNext: Boolean; property Current)
+ tests
compiler: fix for-in loop for arrays. delphi does not copy arrays to a temp variable and it is possible to change array during loop. + test
compiler: add reference for the enumerator operator when it is used + another test for operator enumerator for a class
compiler: add reference for the enumerator operator when it is used + another test for operator enumerator for a class
compiler: enumerator directive support:
+ allow to mark methods and properties by 'enumerator MoveNext' and 'enumerator Current' modifiers. Parser checks return types and duplicates.
+ prefer *marked* by enumerator directive methods and properties than GetEnumerator and Current builtin symbols
+ increase ppu version
+ test
rtl: add IEnumerator and IEnumerable interfaces declarations
tests: for-in loop tests:
+ add small comment at the top of test program
compiler: allow 'enumerator MoveNext' for the interface function declaration + test
compiler: move all for-in loop helpers to the nflw unit
compiler: don't allow the compiler to choose the non-valid enumerator operator for the for-in loop
git-svn-id: trunk@14008 -