Thread: [pygccxml-development] high level API summary
Brought to you by:
mbaas,
roman_yakovenko
From: Roman Y. <rom...@gm...> - 2006-03-07 07:11:09
|
I will try to update Wiki this day, but I am not sure I will have time to i= t. So I post it here. Before you continue to read, remember I don;t want to hurt, I tried to concentrate my efforts on technical aspects only. 1. declaration decorator/wrapper [d d/w] We need to introduce this [d d/w] mainly because pygccxml is standalone pro= ject and it is useful on it's own. The problem is that [d d/w] should solve: eas= y configuration/preparation of declarations for code generator. Right now thi= s is the only use of [d d/w]. In future I do see an other use of [d d/w]. For ex= ample [d d/w] will give user some hints: * why user can not export a function * why user can not finalize a function * why class is noncopyable * why function should be exposed using function signature * why class wrapper is needed * ... I think, that in future we will add an other set of features. What our options to implement this concept: 1. To inject additional properties directly to pygccxml.declarations cl= asses This approach is problematic, because it forces us to implement the functionality as free functions. Good: very simple to implement Bad : there is no one place where user can search for desired functionality this is a fragile hack I don't feel that it is a right way to go. 2. To create single [d d/w] class that using same interface for all declarations. This approach is problematic too. Basically I am talki= ng about DeclWrapper from experimental directory Good: very simple to implement Bad : ( sorry, nothing personal, I just list here technical reasons = ) very fat interface - really, take a look please, it is very difficult to find out what properties are relevant to specific declaratio= n. One of the drawbacks of fat interface is that DeclWrapper shoul= d know of all declarations: class has 4 properties s user can configure operators has different logic to provide reasonable alias ( __getitem__, __call__ ) DeclWrapper implements search functionality. I do believe that search functionality is useful on it's own. So I think it is better to add it to pygccxml.declarations package. The search algorithms impleme= nted by DeclWrapper is too restrictive. I think that DeclWrapper sho= uld provide interface to find/get some declaration, but only some specific declaration wrappers. I do think that we should raise exception= if user tries to search for declarations on a variable. It is possible to implement functionality I talked about, but I think that after implementing part of it, we will see a lot of specia= l cases and we will want to do re factoring on that code. 3. To create separate wrapper for every class. Basically is what I implemented. Now I think about an other solution, almost identical, but instead of use factory design pattern to use __metaclass__. Bad: As Allen said - code complexity. He is 100% right. In order to implement this I needed to change a lot of places. Allen, Matthias and you reader please add you comments here. Good: There is one place to go and see what user can modify. It is possible to implement the functionality I talked. The pla= ce to put this functionality already well defined Only class and namespace declarations should provide search interface. It is easy to create reasonable defaults. For example: decl_wrappers.class_t: def __init__( self ... ) self.__noncopyable =3D None def _get_noncopyable(self): if self.__noncopyable: return self.__noncopyable return declaration.is_noncopyable( self ) def _set_noncopyable(self, flag): if declaration.is_noncopyable( self ) and flag =3D=3D F= alse: raise .... else: self.__noncopyable =3D flag noncopyable =3D property( ..., ..., , "documentation" ) If we implement search algorithm and criteria matcher in pygccxml than our search for some specific declaration is just small redirect= ion def namespace(self, *arguments, **keywords ): if len( arguments ) =3D=3D 1 and not keywords and is_callable( arguments ): return decls_package.matcher.get_single( arguments[0], self.declarations ) else: return decls_package.matcher.get_single( decls_package.namespace_matcher_t( *arguments, **keywords ) , self.declarations ) DeclWrapper has feature: add custom code creators. This is some= thing I should think more about it. This is definitely useful. Right now, I thin 2. module_builder_t is the name of main class, this is the class a user starts to work with. I think all of us agreed to this name. ( I am not talking about some concrete class. ) I think we also agreed that the user should explicitly create the class. It is obvious for us that this class has to provide access to next data structures/functionality: declarations ( =3D=3D declarations wrappers/decorators ) code creators write files It is not obvious whether this class should provide parse method or not. It is obvious for us that user can skip some steps ( parse, create code creators ) and can not skip other( write file ) Allen and Matthias propose is to have 3 functions that will do the job: parse [create]CodeCreators writeFile/createModule It is not obvious from proposal how user should configure that functiona= lity. I vote for next interface: module builder for __init__ method takes as arguments 1. module name 2. files list 3. parser configuration module builder will have 2 get only properties declarations and module_[code]_creator. Those properties will create relevant data structures on demand. So t= hus we eliminate the need of parse method. module builder will have 2 groups of properties: the first one configure parser the second one configure code creators factory code_creators.module_t will get new properties: 1. file name | 2. directory name | this will tell to file writers where to put a code 3. create main 4. ... module builder can provide some shortcuts for those properties. I mea= n that get and set on module builder will just call get and set on modu= le_t class. One area we did not come to agreement is searching/selecting/getting declarations. The first question is whether we should create a group of function that = will return single declaration and an other group that will return multiple declarations aggregated under "multiple declaration wrapper" for easy configuration. My opinion that we should have 2 groups. The reason is simple, we want to write something like this: mb =3D module_builder_t(...) class1 =3D mb.class( name=3D'::interface::data_t' ) memfunc1 =3D class1.member_functions( ... ) The point is that if we will always use multi declaration wrapper then memfunc1 =3D class1.member_functions( ... ) the result of next line will always surprise the user. Also it is very difficult to implement good multi decl wrapper class. Question: should exception be raised when result of search algorithm is None in case multi decl search? We agreed that namespace and class declaration should provide search interface. An other thing that we did not agree is search range. Should we search i= n children declarations too or not. The obvious solution is to add recursive argument to relevant functions. Now the question is what is recursive default val= ue? That's all. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Roman Y. <rom...@gm...> - 2006-03-08 08:28:26
|
Hi. I updated the Wiki. Please take a look. If it possible I would like we = get to decision until end of the week. I also wrote my points in this mail. Thank you. 1. declaration decorator/wrapper [d d/w] We need to introduce this [d d/w] mainly because pygccxml is standalone pro= ject and it is useful on it's own. The problem is that [d d/w] should solve: eas= y configuration/preparation of declarations for code generator. Right now thi= s is the only use of [d d/w]. In future I do see an other use of [d d/w]. For ex= ample [d d/w] will give user some hints: * why user can not export a function * why user can not finalize a function * why class is noncopyable * why function should be exposed using function signature * why class wrapper is needed * ... I think, that in future we will add an other set of features. What our options to implement this concept: 1. To inject additional properties directly to pygccxml.declarations cl= asses This approach is problematic, because it forces us to implement the functionality as free functions. Good: very simple to implement Bad : there is no one place where user can search for desired functionality this is a fragile hack I don't feel that it is a right way to go. 2. To create single [d d/w] class that using same interface for all declarations. This approach is problematic too. Basically I am talki= ng about DeclWrapper from experimental directory Good: very simple to implement Bad : ( sorry, nothing personal, I just list here technical reasons = ) very fat interface - really, take a look please, it is very difficult to find out what properties are relevant to specific declaratio= n. One of the drawbacks of fat interface is that DeclWrapper shoul= d know of all declarations: class has 4 properties s user can configure operators has different logic to provide reasonable alias ( __getitem__, __call__ ) DeclWrapper implements search functionality. I do believe that search functionality is useful on it's own. So I think it is better to add it to pygccxml.declarations package. The search algorithms impleme= nted by DeclWrapper is too restrictive. I think that DeclWrapper sho= uld provide interface to find/get some declaration, but only some specific declaration wrappers. I do think that we should raise exception= if user tries to search for declarations on a variable. It is possible to implement functionality I talked about, but I think that after implementing part of it, we will see a lot of specia= l cases and we will want to do re factoring on that code. 3. To create separate wrapper for every class. Basically is what I implemented. Now I think about an other solution, almost identical, but instead of use factory design pattern to use __metaclass__. Bad: As Allen said - code complexity. He is 100% right. In order to implement this I needed to change a lot of places. Allen, Matthias and you reader please add you comments here. Good: There is one place to go and see what user can modify. It is possible to implement the functionality I talked. The pla= ce to put this functionality already well defined Only class and namespace declarations should provide search interface. It is easy to create reasonable defaults. For example: decl_wrappers.class_t: def __init__( self ... ) self.__noncopyable =3D None def _get_noncopyable(self): if self.__noncopyable: return self.__noncopyable return declaration.is_noncopyable( self ) def _set_noncopyable(self, flag): if declaration.is_noncopyable( self ) and flag =3D=3D F= alse: raise .... else: self.__noncopyable =3D flag noncopyable =3D property( ..., ..., , "documentation" ) If we implement search algorithm and criteria matcher in pygccxml than our search for some specific declaration is just small redirect= ion def namespace(self, *arguments, **keywords ): if len( arguments ) =3D=3D 1 and not keywords and is_callable( arguments ): return decls_package.matcher.get_single( arguments[0], self.declarations ) else: return decls_package.matcher.get_single( decls_package.namespace_matcher_t( *arguments, **keywords ) , self.declarations ) DeclWrapper has feature: add custom code creators. This is some= thing I should think more about it. This is definitely useful. Right now, I thin 2. module_builder_t is the name of main class, this is the class a user starts to work with. I think all of us agreed to this name. ( I am not talking about some concrete class. ) I think we also agreed that the user should explicitly create the class. It is obvious for us that this class has to provide access to next data structures/functionality: declarations ( =3D=3D declarations wrappers/decorators ) code creators write files It is not obvious whether this class should provide parse method or not. It is obvious for us that user can skip some steps ( parse, create code creators ) and can not skip other( write file ) Allen and Matthias propose is to have 3 functions that will do the job: parse [create]CodeCreators writeFile/createModule It is not obvious from proposal how user should configure that functiona= lity. I vote for next interface: module builder for __init__ method takes as arguments 1. module name 2. files list 3. parser configuration module builder will have 2 get only properties declarations and module_[code]_creator. Those properties will create relevant data structures on demand. So t= hus we eliminate the need of parse method. module builder will have 2 groups of properties: the first one configure parser the second one configure code creators factory code_creators.module_t will get new properties: 1. file name | 2. directory name | this will tell to file writers where to put a code 3. create main 4. ... module builder can provide some shortcuts for those properties. I mea= n that get and set on module builder will just call get and set on modu= le_t class. One area we did not come to agreement is searching/selecting/getting declarations. The first question is whether we should create a group of function that = will return single declaration and an other group that will return multiple declarations aggregated under "multiple declaration wrapper" for easy configuration. My opinion that we should have 2 groups. The reason is simple, we want to write something like this: mb =3D module_builder_t(...) class1 =3D mb.class( name=3D'::interface::data_t' ) memfunc1 =3D class1.member_functions( ... ) The point is that if we will always use multi declaration wrapper then memfunc1 =3D class1.member_functions( ... ) the result of next line will always surprise the user. Also it is very difficult to implement good multi decl wrapper class. Question: should exception be raised when result of search algorithm is None in case multi decl search? We agreed that namespace and class declaration should provide search interface. An other thing that we did not agree is search range. Should we search i= n children declarations too or not. The obvious solution is to add recursive argument to relevant functions. Now the question is what is recursive default val= ue? That's all. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |