The classes in "fgl.pas" implement an enumerator in the generic class "TFPGListEnumerator" and "specialize" that inside themselves. If we now specialize one of the generic classes (e.g. "TFPGList") the "TFPGListEnumerator" is really specialized as well. That means a def is added to the global symtable (the local one in case of a program or library file). If we now use the enumerator class in the same file (e.g. by using a "for ... in", which has a temporary variable of that type) then the methods of the enumerator are specialized again (the def itself is not). To avoid this (and time consuming searches for existing method specializations) we flag the specialized def as "done" once we're finished.
symconst.pas
* add a new flag "df_methods_specialized" to the "tdefoption" enumeration
psub.pas, process_abstractrecorddef
* check the def for the "df_methods_specialized" flag and continue only if that is not set
* set the "df_methods_specialized" flag before leaving the function
git-svn-id: branches/svenbarth/generics@19432 -
symtable.pas:
* reduce the "childdef" parameter of "is_owned_by" from "tabstractrecorddef" to "tdef", so that more primitive defs can be checked as well
* add a new function "sym_is_owned_by" which is similar to "is_owned_by", but takes a symbol and a symtable as parameter; the owner chain of the symtable is checked until a non-object- and non-record-symtable is reached
ptype.pas:
* extend "id_type", so that the symbol and the symtable that belongs to the returned def is returned as well
* this is needed to check inside "single_type" whether a def that is a generic was specialized inside another generic, because in that case the genericdef is returned by "generate_specialization" and not a new specialized def, but the corresponding type symbol (which is different from "hdef.typesym") belongs to the class itself; I need to admit that this solution isn't very clean and one could try to circumvent some of the checks, so I need to find a better detection for such a case (concrete example: the enumerator specialization inside the classes of "fgl.pas")
* in "read_named_type.expr_type" the check for "df_generic" is extended analogous to the previous change, but instead of relying on the symbol it uses the def. This is needed so that types like method pointers that are defined inside the current generic are not disallowed as they contain the "df_generic" flag as well; like the previous change this change isn't clean either and maybe it's better to remove the inclusion of the "df_generic" flag from everything except records and "objects" inside records/"objects" again. Such a solution will "only" reduce the problem to records and "objects" though...
pgenutil.pas:
* only add a new undefined def if we're not parsing the parent class or interfaces ("parse_class_parent" is true), otherwise the InternalError regarding the "equal count of defs" will trigger
* there are now two cases where we need to return a generic def instead of a undefined one when we're parsing a generic:
a) we have the previously mentioned case that "parse_class_parent" is true
b) an undefined def was added, but we need to return a generic def, so that checks can be passed
* use the correct variable when building the generic name, otherwise we get errors like "identifier '$1' not found"
* don't push the symtable if we're currently parsing the list of interfaces or the parent class, because then e.g. a generic interface will be included in the symtable of the implementing class which isn't what we want; the current solution is not clean though, so this needs to be investigated more
* Note: In the current state of "generate_specialization" the function could be simplyfied a bit more; this will be done when the implementation is satisfactory enough
git-svn-id: branches/svenbarth/generics@19430 -
* symconst.pas:
add an entry for the generic dummy symbol to the symbol options enumeration
* pgenutil.pas:
- extend "generate_specialization" by the possibility to pass a symbol name instead of a def
- if "symname" is given that is used; otherwise "genericdef" or "tt" is used
* pexpr.pas:
- in case of "<" we are trying to receive a generic dummy symbol from the left node (new function "getgenericsym")
- it's name is then passed to "generate_specialization" which in turn fills genericdef
- adjust call to "generate_specialization"
* pdecl.pas:
- we can now check for "sp_generic_dummy instead of "not sp_generic_para" to check whether we've found the dummy symbol of a previous generic declaration
- if a new dummy symbol is created we need to include "sp_generic_dummy"
- if we've found a non-generic symbol with the same name we need to include the "sp_generic_dummy" flag as well
* symtable.pas
- add a new function "searchsym_with_symoption" that more or less works the same as "searchsym", but only returns successfully if the found symbol contains the given flag
- "searchsym_with_symoption" and "searchsym" are based on the same function "maybe_searchsym_with_symoption" which is the extended implementation of "searchsym" (note: object symtables are not yet searched if a symoption is to be looked for)
- add a function "handle_generic_dummysym" which can be used to hide the undefineddef symbol in a symtable
- correctly handle generic dummy symbols in case of variables in "tstaticsymtable.checkduplicate"
git-svn-id: branches/svenbarth/generics@19429 -
- fix a comment
- the created undefineddef must not be freed, as the count of the list the def is contained in, is used to find other defs again
git-svn-id: branches/svenbarth/generics@19428 -
pgenutils.pas/generate_specialization:
- parse hint directives of the generic if they are recorded
- output hint messages of the generic after the ">" is successfully parsed
pexpr.pas:
- factor: don't display hints of a potential generic type if the next token is a "<"
- sub_expr:
* added two inline methods which
a) checks whether a node is a typenode or a loadvmtaddrnode with a typenode
b) returns the typedef of such a node
* check hint directives for the first parsed type argument of a specialization
* in the case of parsing a non-generic type the hints of the left and right node of the resulting "<" node need to be checked (the right ones only if another "<" is following)
git-svn-id: branches/svenbarth/generics@19427 -
This fixes the compilation of test tests\test\tgeneric29.pp and the reminder in pdecobj.pas is not needed anymore.
Note: Perhaps this behavior should be enabled in general if "parse_generic" is true (and not only if parse_parent_class if true as well).
git-svn-id: branches/svenbarth/generics@19426 -
Reasons for the "unique symbol" approach:
- no special search operations for cross unit search needed (which is supported by Delphi) => less performance impact
- no special care needed to really find the correct generic => less increase of parser complexity
Currently all generic tests except tgeneric29.pp compile and inline specializations work as well.
The changes in detail:
* pdecl.pas/types_dec:
- The variables used to hold the final name of the symbol are now prefixed with "gen". In case of non-generics the prefixed ones are equal to the non-prefixed ones (e.g. orgtypename=genorgtypename). In case of a generic symbol the "gen"-variants contain the type parameter count suffix (e.g. '$1' in case of 'TTest<T>') as well.
- The unmodified pattern is used to insert and detect a dummy symbol with that name, so that type declarations and - more important - inline specializations can find that symbol.
- In non-Delphi modes this symbol is also used to detect whether we have a type redefinition which is not allowed currently; its typedef points to the generic def.
- In mode Delphi the def of that dummy symbol (which contains an undefineddef) is modified when a corresponding non-generic type is parsed, so that it contains the def of the real type.
* pdecsub.pas/parse_proc_head
- consume_generic_type_parameter now only parses the type parameters and picks the generic with the correct amount of parameters. The verification of the order and names of the parameters needs to be added again.
- it also does not use "def" anymore, but it sets "srsym"
- in parse_proc_head the symbol (srsym) is only searched if the symbol isn't assigned already; in case of a generic in mode FPC it will find the dummy symbol that points to the generic def
* pexpr.pas
- in factor_read_id there are three cases to handle:
+ the symbol is not assigned => error
+ a possible generic symbol (either an undefined def or the non-generic variant) => no error and no hints
+ a non-generic symbol => hints
Point 1 is handled correctly, point 2 and 3 aren't currently and also they might be needed to be moved somewhere else
- sub_expr:
+ a node can be a tloadvmtaddrnode as well if the non-generic variant of a generic symbol is a class
+ we can only check afterwards whether the specialization was successful
* pgenutil.pas/generate_specialization
using the count of the parsed types the correct symbol can be found easily
git-svn-id: branches/svenbarth/generics@19424 -
don't accept the generic dummy symbol if the next token isn't a "<"
sub_expr:
generate an error if we had a normal "<" comparison containing the dummy symbol on the left side instead of a specialization
git-svn-id: branches/svenbarth/generics@18003 -
pobjdec.pas (object_dec) / ptype.pas (record_dec, array_dec, procvar_dec):
- enable "parse_generic" if a nested type is parsed and we're already inside a generic (this prevents code to be generated for the nested type's methods)
- set the "df_specialization" flag so that the code for generating the methods (and thus resolving the forwards declarations) is called for this symbol
pexpr.pas:
add "post_comp_expr_gendef" which basically calls "handle_factor_typenode" and "postfixoperators" as those aren't exported from the unit themselves
ptype.pas, read_named_type.expr_type:
- use "post_comp_expr_gendef" to parse the use of nested types (e.g. "var t: TTest<T>.TTestSub")
psub.pas, specialize_objectdefs:
implement the generation of the method bodies for nested structures (resolves the forward declarations)
pdecl.pas, types_dec:
when we encounter a nested structure inside a specialization of a structure, we need to find the corresponding generic definition so that the generic can be correctly parsed later on.
git-svn-id: branches/svenbarth/generics@18002 -
This fixes the compilation of test tests\test\tgeneric29.pp and the reminder in pdecobj.pas is not needed anymore.
Note: Perhaps this behavior should be enabled in general if "parse_generic" is true (and not only if parse_parent_class if true as well).
git-svn-id: branches/svenbarth/generics@17996 -
* win/systhrd.inc: added error checking in several places. Fail with code 226 if resources cannot be allocated, as Delphi does.
* win/syswin.inc, Dll_entry: Don't call DoneThread in PROCESS_DETACH callback, it is redundant because the main thread is finalized by FPC_DO_EXIT. SysReleaseThreadVars is still necessary. Also removed redundant assignments to return value.
git-svn-id: trunk@17992 -
- removed assembler from SysRelocateThreadVars: never actually worked, and this file is shared between different CPUs - not a proper place for assembler anyway.
- Obtain handle of kernel32.dll using GetModuleHandle, allows to get rid of UnloadLibrary call.
git-svn-id: trunk@17975 -
to cleanup more than one target using distclean.
* Added new fpmakeclean target to makefiles which does a cleanall and clears
the fpmake executables
git-svn-id: trunk@17969 -