From 52667b6822dd8aaaf70651235111146ef89ebeb1 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 31 Dec 2010 03:43:16 +0000 Subject: [PATCH] compiler: implement generics for records based on generic objects implementation + 1 test git-svn-id: trunk@16670 - --- .gitattributes | 1 + compiler/pdecobj.pas | 3 ++- compiler/pdecsub.pas | 8 ++++---- compiler/psub.pas | 4 ++-- compiler/ptype.pas | 39 +++++++++++++++++++++++++++++++-------- tests/test/tgeneric24.pp | 19 +++++++++++++++++++ 6 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 tests/test/tgeneric24.pp diff --git a/.gitattributes b/.gitattributes index 880e0c2621..23e7a32e1e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9412,6 +9412,7 @@ tests/test/tgeneric20.pp svneol=native#text/pascal tests/test/tgeneric21.pp svneol=native#text/pascal tests/test/tgeneric22.pp svneol=native#text/pascal tests/test/tgeneric23.pp svneol=native#text/pascal +tests/test/tgeneric24.pp svneol=native#text/pascal tests/test/tgeneric3.pp svneol=native#text/plain tests/test/tgeneric4.pp svneol=native#text/plain tests/test/tgeneric5.pp svneol=native#text/plain diff --git a/compiler/pdecobj.pas b/compiler/pdecobj.pas index 25f70e6d8c..f03ae6e293 100644 --- a/compiler/pdecobj.pas +++ b/compiler/pdecobj.pas @@ -37,6 +37,7 @@ interface function constructor_head:tprocdef; function destructor_head:tprocdef; procedure struct_property_dec(is_classproperty:boolean); + procedure insert_generic_parameter_types(genericdef:tstoreddef;genericlist:TFPObjectList); implementation @@ -591,7 +592,7 @@ implementation pd : tprocdef; has_destructor, oldparse_only, - old_parse_generic : boolean; + old_parse_generic: boolean; object_member_blocktype : tblock_type; fields_allowed, is_classdef, classfields: boolean; vdoptions: tvar_dec_options; diff --git a/compiler/pdecsub.pas b/compiler/pdecsub.pas index 7ee7e400d3..3679cc44c7 100644 --- a/compiler/pdecsub.pas +++ b/compiler/pdecsub.pas @@ -1152,9 +1152,9 @@ implementation old_current_specializedef:=current_specializedef; current_structdef:=pd.struct; if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then - current_genericdef:=tobjectdef(current_structdef); + current_genericdef:=current_structdef; if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then - current_specializedef:=tobjectdef(current_structdef); + current_specializedef:=current_structdef; end; { Add parameter symtable } if pd.parast.symtabletype<>staticsymtable then @@ -1207,9 +1207,9 @@ implementation old_current_specializedef:=current_specializedef; current_structdef:=pd.struct; if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then - current_genericdef:=tobjectdef(current_structdef); + current_genericdef:=current_structdef; if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then - current_specializedef:=tobjectdef(current_structdef); + current_specializedef:=current_structdef; end; single_type(pd.returndef,false,false); diff --git a/compiler/psub.pas b/compiler/psub.pas index 8fe33302c5..9667612660 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -1401,9 +1401,9 @@ implementation current_procinfo:=self; current_structdef:=procdef.struct; if assigned(current_structdef) and (df_generic in current_structdef.defoptions) then - current_genericdef:=tobjectdef(current_structdef); + current_genericdef:=current_structdef; if assigned(current_structdef) and (df_specialization in current_structdef.defoptions) then - current_specializedef:=tobjectdef(current_structdef); + current_specializedef:=current_structdef; { calculate the lexical level } if procdef.parast.symtablelevel>maxnesting then diff --git a/compiler/ptype.pas b/compiler/ptype.pas index 6b79e9d860..75bd74d3de 100644 --- a/compiler/ptype.pas +++ b/compiler/ptype.pas @@ -835,12 +835,21 @@ implementation end; { reads a record declaration } - function record_dec(const n:tidstring):tdef; + function record_dec(const n:tidstring;genericdef:tstoreddef;genericlist:TFPObjectList):tdef; var - old_current_structdef : tabstractrecorddef; - recst : trecordsymtable; + old_current_structdef, + old_current_genericdef, + old_current_specializedef: tabstractrecorddef; + old_parse_generic: boolean; + recst: trecordsymtable; begin old_current_structdef:=current_structdef; + old_current_genericdef:=current_genericdef; + old_current_specializedef:=current_specializedef; + old_parse_generic:=parse_generic; + + current_genericdef:=nil; + current_specializedef:=nil; { create recdef } recst:=trecordsymtable.create(n,current_settings.packrecords); current_structdef:=trecorddef.create(n,recst); @@ -849,20 +858,34 @@ implementation symtablestack.push(recst); { parse record } consume(_RECORD); + + { usage of specialized type inside its generic template } + if assigned(genericdef) then + current_specializedef:=current_structdef + { reject declaration of generic class inside generic class } + else if assigned(genericlist) then + current_genericdef:=current_structdef; + + insert_generic_parameter_types(genericdef,genericlist); + parse_generic:=(df_generic in current_structdef.defoptions); if m_advanced_records in current_settings.modeswitches then parse_record_members else begin - read_record_fields([vd_record]); - consume(_END); - end; + read_record_fields([vd_record]); + consume(_END); + end; { make the record size aligned } recst.addalignmentpadding; { restore symtable stack } symtablestack.pop(recst); if trecorddef(current_structdef).is_packed and is_managed_type(current_structdef) then Message(type_e_no_packed_inittable); + { restore old state } + parse_generic:=old_parse_generic; current_structdef:=old_current_structdef; + current_genericdef:=old_current_genericdef; + current_specializedef:=old_current_specializedef; end; @@ -1279,7 +1302,7 @@ implementation end; _RECORD: begin - def:=record_dec(name); + def:=record_dec(name,genericdef,genericlist); end; _PACKED, _BITPACKED: @@ -1314,7 +1337,7 @@ implementation def:=object_dec(odt_object,name,genericdef,genericlist,nil); end; else - def:=record_dec(name); + def:=record_dec(name,genericdef,genericlist); end; current_settings.packrecords:=oldpackrecords; end; diff --git a/tests/test/tgeneric24.pp b/tests/test/tgeneric24.pp new file mode 100644 index 0000000000..f2e85c388e --- /dev/null +++ b/tests/test/tgeneric24.pp @@ -0,0 +1,19 @@ +program project1; + +{$mode objfpc}{$H+} +{$apptype console} + +type + generic TFoo = record + F: T; + end; +var + FooInt: specialize TFoo; + FooStr: specialize TFoo; +begin + FooInt.F := 1; + WriteLn(FooInt.F); + FooStr.F := 'test'; + WriteLn(FooStr.F); +end. +