[fpc-devel] class-attributes

2012-05-24 Thread Joost van der Sluis
On 17 May 2012, at 23:32, Joost van der Sluis wrote:

 I'm trying to implement extended RTTI property attributes as
 supported by recent Delphi versions.

Please add this functionality first to a separate branch for easier
reviewing.

I could, but I attached a patch first. Before I commit this to a branch
I want to know that I'm on the right track. Could you and/or others have
a look at the patch?

I'm especially interested if things are done in the right units, and if
the code in ptypes.pas is acceptable.

Attached are the patch and a simple test-program. 

First an example what class-attributes are:

type
  TMyObject = class
  published
[TAttributeClassName('param1','param2')]
property AProperty;
  end;

When you request the class-property that belongs to the property
AProperty, then you get an instance of the TAttributeClassName class
which is constructed by calling it's constructor with the supplied
parameters. (In this case 'param1' and 'param2')

How I implemented this:
For each attribute a function is generated that returns a class-instance
of the attribute. This function is generated in ptypes by creating a
tcgprocinfo. All the necessary nodes are added to it and then
tcgprocinfo.generate_code is executed.

In the rtti-info (ppropinfo) the address of this function is stored so
that it is possible to read those attributes.

If I'm on the right track I'll add a branch with this patch and work
from there. Some issues:

- In Delphi an attribute-class has to be defined as a TCustomAttribute.
That way it's also clear which constructor has to be called. For now, it
calls the first constructor it can find.

- The rtti-info is now stored inside PPropInfo, I don't think that this
is how Delphi does it, also because in Delphi you need the 'rtti' unit
to get this information. I've added it to typinfo and later on a 'rtti'
unit could be written as a wrapper around typinfo.

- When we add more rtti-information to types we need a way to specify
what to generate and what not and where to store it. Especially because
the rtti-info will grow. 

- No error is generated when you define an attribute for something else
then a property.

- The attribute-definition is stored in the .ppu, but that's not really
needed. Since at compile-time this information is never used by another
unit. I used it for debugging though (with ppudump) A side-effect is
that when an attribute is changed, a recompilation of the unit is
forced. Do we want that? (For now only the attribute-type is stored in
the ppu, not the parameters)

Joost.







-- 
Met vriendelijke groeten,

  Joost van der Sluis
  CNOC Informatiesystemen en Netwerken
  http://www.cnoc.nl
Index: compiler/ptype.pas
===
--- compiler/ptype.pas	(revision 21375)
+++ compiler/ptype.pas	(working copy)
@@ -60,11 +60,14 @@
 { parse hint directives (platform, deprecated, ...) for a procdef }
 procedure maybe_parse_hint_directives(pd:tprocdef);
 
+{ generate hidden RTTI attribute functions which return the attribute classes }
+procedure generate_rttiattribute_procs;
+
 implementation
 
 uses
{ common }
-   cutils,
+   cutils,sysutils,pparautl,
{ global }
globals,tokens,verbose,constexp,
systems,
@@ -80,10 +83,11 @@
fmodule,
{ pass 1 }
node,ncgrtti,nobj,
-   nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,
+   nmat,nadd,ncal,nset,ncnv,ninl,ncon,nld,nflw,nmem,nbas,
+   ncgutil,
{ parser }
scanner,
-   pbase,pexpr,pdecsub,pdecvar,pdecobj,pdecl,pgenutil
+   pbase,pexpr,pdecsub,pdecvar,pdecobj,pdecl,pgenutil,psub
 {$ifdef jvm}
,pjvm
 {$endif}
@@ -1618,7 +1622,138 @@
 read_named_type(def,nil,nil,nil,parseprocvardir);
   end;
 
+procedure generate_rttiattribute_proc(APropertySym: tpropertysym; AnAttribute: trtti_attribute; attribute_index: longint);
+var
+  pd: tprocdef;
+  aprocsym: tprocsym;
+  st:TSymtable;
+  checkstack : psymtablestackitem;
+  old_current_procinfo : tprocinfo;
+  old_current_structdef: tabstractrecorddef;
+  old_current_genericdef,
+  old_current_specializedef: tstoreddef;
+  block: tblocknode;
+  load: tloadnode;
+  statement: tstatementnode;
+  call: tcallnode;
+  assignment: tassignmentnode;
+  constrdef: tprocdef;
+  vmtaddrnode: tloadvmtaddrnode;
+begin
+  aprocsym:=tprocsym.create(make_mangledname('_RTTI_ATTRIBUTE_',symtablestack.top,APropertySym.Name+'_'+IntToStr(attribute_index)));
+  symtablestack.top.insert(aprocsym);
+  aprocsym.visibility:=vis_hidden;
 
+  st:=nil;
+  checkstack:=symtablestack.stack;
+  while assigned(checkstack) do
+begin
+  st:=checkstack^.symtable;
+  if st.symtabletype in [staticsymtable,globalsymtable,localsymtable] then
+break;
+  checkstack:=checkstack^.next;
+end;
+  

Re: [fpc-devel] class-attributes

2012-05-24 Thread Sven Barth

On 24.05.2012 15:27, Joost van der Sluis wrote:

On 17 May 2012, at 23:32, Joost van der Sluis wrote:


I'm trying to implement extended RTTI property attributes as
supported by recent Delphi versions.



Please add this functionality first to a separate branch for easier
reviewing.


I could, but I attached a patch first. Before I commit this to a branch
I want to know that I'm on the right track. Could you and/or others have
a look at the patch?

I'm especially interested if things are done in the right units, and if
the code in ptypes.pas is acceptable.

Attached are the patch and a simple test-program.


Some small remarks that I noticed:

* please call your generate_rttiattribute_procs after the 
generate_specialization_procs as methods of generics could force the 
specialization of a class that is not yet specialized, but that carries 
attributes
* maybe it's better not to generate attribute data for generics, I don't 
know... (simply check for df_generic in ttypesym(p).typedef.defoptions 
in generate_rttiattribute_procs_classes)
* in generate_rttiattribute_procs_properties you also need to handle 
nested classes

* you should increase the PPU version in ppu.pas as you added a new field
* you might want to call me blind, but where did you add the field 
rtti_attributesdef to, to which you assign the current_rttiattributedef? 
(can it be that you forgot that in the patch?)


And two questions:
* does the usage of attributes with methods/fields depend on the 
availability of the extended RTTI?
* can attributes also be used with records in Delphi? (as they can now 
carry properties as well)


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel


Re: [fpc-devel] class-attributes

2012-05-24 Thread Joost van der Sluis
On Thu, 2012-05-24 at 18:48 +0200, Sven Barth wrote:
 On 24.05.2012 15:27, Joost van der Sluis wrote:
  On 17 May 2012, at 23:32, Joost van der Sluis wrote:
  I could, but I attached a patch first. Before I commit this to a branch
  I want to know that I'm on the right track. Could you and/or others have
  a look at the patch?

 * please call your generate_rttiattribute_procs after the 
 generate_specialization_procs as methods of generics could force the 
 specialization of a class that is not yet specialized, but that carries 
 attributes

Ok, I'll change that.

 * maybe it's better not to generate attribute data for generics, I don't 
 know... (simply check for df_generic in ttypesym(p).typedef.defoptions 
 in generate_rttiattribute_procs_classes)

I'll will look what Delphi does. In principle i don't a reason why it
shouldn't work.

 * in generate_rttiattribute_procs_properties you also need to handle 
 nested classes

Ah yes, offcourse. I will also look at the 'normal' rtti generation, I
copied the code from there. Maybe that there is no rtti information
generated for nested classes at all at this moment.

 * you might want to call me blind, but where did you add the field 
 rtti_attributesdef to, to which you assign the current_rttiattributedef? 
 (can it be that you forgot that in the patch?)

See the second change in pdecobj. (In procedure truct_property_dec) 

 And two questions:
 * does the usage of attributes with methods/fields depend on the 
 availability of the extended RTTI?

Yes. Without extended RTTI you can not get a list of method/fields at
runtime. So where should the attributes be bound to?

 * can attributes also be used with records in Delphi? (as they can now 
 carry properties as well)

I don't know. Do we support rtti on records? I think this is also a part
of what Delphi calls 'extended rtti'.

Joost

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


Re: [fpc-devel] class-attributes

2012-05-24 Thread Sven Barth

On 24.05.2012 20:07, Joost van der Sluis wrote:

On Thu, 2012-05-24 at 18:48 +0200, Sven Barth wrote:

On 24.05.2012 15:27, Joost van der Sluis wrote:

On 17 May 2012, at 23:32, Joost van der Sluis wrote:
I could, but I attached a patch first. Before I commit this to a branch
I want to know that I'm on the right track. Could you and/or others have
a look at the patch?



* please call your generate_rttiattribute_procs after the
generate_specialization_procs as methods of generics could force the
specialization of a class that is not yet specialized, but that carries
attributes


Ok, I'll change that.



Thanks.


* maybe it's better not to generate attribute data for generics, I don't
know... (simply check for df_generic in ttypesym(p).typedef.defoptions
in generate_rttiattribute_procs_classes)


I'll will look what Delphi does. In principle i don't a reason why it
shouldn't work.



I don't know whether you can query the RTTI of a generic class at all 
(note: I talk about the generic itself, not a specialization of it); 
also the RTTI generation in FPC is already disabled for generics (as 
well as the VMT generation).



* in generate_rttiattribute_procs_properties you also need to handle
nested classes


Ah yes, offcourse. I will also look at the 'normal' rtti generation, I
copied the code from there. Maybe that there is no rtti information
generated for nested classes at all at this moment.



If so this should be fixed AFAIK.


* you might want to call me blind, but where did you add the field
rtti_attributesdef to, to which you assign the current_rttiattributedef?
(can it be that you forgot that in the patch?)


See the second change in pdecobj. (In procedure truct_property_dec)



Yes, I see the change in pdecobj, but I'm missing the change in the 
class where p is an instance of. Ah... now I found what I was looking 
for: the change in symsym.pas... ^^



And two questions:
* does the usage of attributes with methods/fields depend on the
availability of the extended RTTI?


Yes. Without extended RTTI you can not get a list of method/fields at
runtime. So where should the attributes be bound to?



Ok... then it's indeed better to wait with attributes for other class 
members besides properties until the extended RTTI is added as well.



* can attributes also be used with records in Delphi? (as they can now
carry properties as well)


I don't know. Do we support rtti on records? I think this is also a part
of what Delphi calls 'extended rtti'.


I don't know either. I just wanted to ask out of completeness ^^

Otherwise from the perspective of a junior compiler developer the 
patch looks ok. :) [I haven't tested it yet though]


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-devel