itcl::body somemethod {} {
# the next method is in the classes hierarchy!!
some_class_method Hello World
}
The problem is that for the new OO system there is a "my" needed in front of
the call to some_class_method ( "my some_class_method Hello World" ).
To not change the behaviour of the current OO implementation it would be
enough to allow to add some resolver procs to an object. That might also be
necessary for other oo extensions.
A solution to that problem would be to add a C-function to the new OO system
to allow to register resolver procs and to add a call to
Tcl_SetNamespaceResolvers(...) when creating an object.
With that solution the problem could be overcome (I have done some simple
test with a test implementation).
A sample implementation is appended.
Comments are welcome
Arnulf (APW in the wiki)
===================== register resolver functionality ===================
/* ARNULF BEGIN */
/* functionality for adding/deleting namespace resolvers best at beginning
of tclOO.c */
int TclOOAddResolverScheme(
Tcl_Interp *interp,
const char *name,
Tcl_ResolveCmdProc *cmdResProc,
Tcl_ResolveVarProc *varResProc,
Tcl_ResolveCompiledVarProc *compiledVarResProc);
int TclOODeleteResolverScheme(const char *name);
/* next 2 lines should be better placed in the Foundation!! */
static ResolverScheme *ResolverSchemes = NULL;
static int numResolverSchemes = 0;
int TclOOAddResolverScheme(
Tcl_Interp *interp, /* The interpreter to install into. */
const char *name, /* the name of the extension that
* called us */
Tcl_ResolveCmdProc *cmdResProc, /* resolver proc for commands */
Tcl_ResolveVarProc *varResProc, /* resolver proc for variables */
Tcl_ResolveCompiledVarProc *compiledVarResProc) /* resolver proc for
* compiled variables */
{
Interp *iPtr = (Interp *) interp;
Foundation *fPtr = iPtr->ooFoundation;
ResolverScheme *resolverSchemePtr;
#ifdef RESOLVERS_ARE_IN_FOUNDATION
fPtr->numResolverSchemes++;
if (fPtr->ResolverSchemes == NULL) {
fPtr->ResolverSchemes = (ResolverScheme
*)ckalloc(sizeof(ResolverScheme)
);
} else {
fPtr->ResolverSchemes = (ResolverScheme *)ckrealloc((void
*)ResolverSche
mes, numResolverSchemes * sizeof(ResolverScheme));
}
resolverSchemePtr = &fPtr->ResolverSchemes[numResolverSchemes-1];
#else
numResolverSchemes++;
if (ResolverSchemes == NULL) {
ResolverSchemes = (ResolverScheme *)ckalloc(sizeof(ResolverScheme));
} else {
ResolverSchemes = (ResolverScheme *)ckrealloc((void
*)ResolverSchemes, numResolverSchemes * sizeof(ResolverScheme));
}
resolverSchemePtr = &ResolverSchemes[numResolverSchemes-1];
#endif
resolverSchemePtr->name = (char *)ckalloc(strlen(name)+1);
strcpy(resolverSchemePtr->name, name);
resolverSchemePtr->cmdResProc = cmdResProc;
resolverSchemePtr->varResProc = varResProc;
resolverSchemePtr->compiledVarResProc = compiledVarResProc;
return TCL_OK;
}
int TclOODeleteResolverScheme(const char *name)
{
/* TO BE FILLED!!! */
return TCL_OK;
}
/* ARNULF END */
===================== call of Tcl_SetNamespaceResolvers ===================
/* ARNULF BEGIN */
/* to be added on tclOO.c function AllocObject before initializing traces */
{
ResolverScheme *resolverSchemePtr;
int i = 0;
#ifdef RESOLVERS_ARE_IN_FOUNDATION
for (i = 0; i < fPtr->numResolverSchemes; i++) {
resolverSchemePtr = &fPtr->ResolverSchemes[i];
Tcl_SetNamespaceResolvers(oPtr->namespacePtr,
resolverSchemePtr->cmdResProc,
resolverSchemePtr->varResProc,
resolverSchemePtr->compiledVarResProc);
}
#else
for (i = 0; i < numResolverSchemes; i++) {
resolverSchemePtr = &ResolverSchemes[i];
Tcl_SetNamespaceResolvers(oPtr->namespacePtr,
resolverSchemePtr->cmdResProc,
resolverSchemePtr->varResProc,
resolverSchemePtr->compiledVarResProc);
}
#endif
===========================================================================
If the resolver is added to the object's namespace, that should do the
trick. In turn, the best way to do that would be to subclass the basic
oo::object and oo::class and attach the extra code in there. That
_should_ do the trick. (The 'my' is needed in the basic OO system
because methods are not actually standard Tcl commands. This is because
there's two sources of context data they need instead of the more
conventional single ClientData of a normal command; the other context
is the info about which object this is, etc.)
I don't as yet know whether I've exposed all the right API needed in
order to enable the addition of constructors without contortions.
That's something I'd love feedback on - I'm far too close to the code
to see what's missing - so your message is very helpful. (FWIW, if
you're developing extensions you can't build them with stubs yet
because none of the OO C API is in the stub table; I'm not planning to
fix that before any merge into the main development trunk because I
have no idea what the stub table indices are going to be.)
Donal.
> Arnulf Wiedemann wrote:
>> The problem is that for the new OO system there is a "my" needed in front
>> of the call to some_class_method ( "my some_class_method Hello World" ).
>>
>> To not change the behaviour of the current OO implementation it would be
>> enough to allow to add some resolver procs to an object. That might also
>> be necessary for other oo extensions.
>
> If the resolver is added to the object's namespace, that should do the
> trick.
Would that also work if it is written in C and has a Tcl command to call it?
> In turn, the best way to do that would be to subclass the basic
> oo::object and oo::class and attach the extra code in there. That
> _should_ do the trick. (The 'my' is needed in the basic OO system
> because methods are not actually standard Tcl commands.
The resolver is just adding the "my" in front of the call if its within the
appropriate context and the method is visible concerning Itcl's rules and
adds an evaluation call for doing the stuff.
> This is because
> there's two sources of context data they need instead of the more
> conventional single ClientData of a normal command; the other context
> is the info about which object this is, etc.)
OK, I will try that and report to you.
>
> I don't as yet know whether I've exposed all the right API needed in
> order to enable the addition of constructors without contortions.
> That's something I'd love feedback on - I'm far too close to the code
> to see what's missing - so your message is very helpful.
Another problem I have found out is, that Itcl has variables on a class
base, not on an object base. Every class can have instance variables, which
are not shared: "private variable somevariable". I think such a construct
is not possible at the moment using the OO system.
What also would be helpful if there would be a 3rd protection level, so one
could have private, protected and public methods/variables. The rules are:
private: only in the class they are defined
protected: only in the class they are defined and in all derived classes
(subclasses)
public: visible from outside of the class/object
Maybe that could be done with a command "localexport" for the protected
stuff, "unexport" could correspond to private and "export" to public. For
Methods that is already working besides the "protected" part, for variables
I see some problems (especially with the "public" part)
Having that would make it relativly easy to implement Itcl on top of OO
system.
> (FWIW, if
> you're developing extensions you can't build them with stubs yet
> because none of the OO C API is in the stub table; I'm not planning to
> fix that before any merge into the main development trunk because I
> have no idea what the stub table indices are going to be.)
No problem yet, I m just trying to get Itcl running on top of OO system and
at the moment I am working in the "Tcl" directory having a small C-library
which is loaded using the load command and some Tcl code used as a
"preprocessor" to convert Itcl code to the calls of the new OO system.
Right know for learning about how to do that I am calling the non-static
methods in the OO system (have to use the stubs interface later on).
In the past I did only program with Itcl for about 10 years, but it seems
interesting to dive into the internals. :-)
Arnulf
>
> Donal.
Rock on!
Time for an Itcl 4.0, eh?
- --
David Gravereaux <davy...@pobox.com>
[species:human; planet:earth,milkyway(western spiral arm),alpha sector]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
iD8DBQFFKZJKlZadkQh/RmERAvyDAJ44rmjbNozMjSTQzcPS1nYdygtIQACg8NcA
f61PQIpZm8Aw0g9bUeZ1Gn8=
=/dNv
-----END PGP SIGNATURE-----
Arnulf Wiedemann wrote:
> What also would be helpful if there would be a 3rd protection level, so one
> could have private, protected and public methods/variables. The rules are:
>
> private: only in the class they are defined
> protected: only in the class they are defined and in all derived classes
> (subclasses)
> public: visible from outside of the class/object
>
Yes, thank you.. The protected level never worked right in Tcl post 8.0
due to a slightly broken (still currently, IINM) namespace API compared
to Itcl's original 7.6 time-frame namespace patch.
- --
David Gravereaux <davy...@pobox.com>
[species:human; planet:earth,milkyway(western spiral arm),alpha sector]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
iD8DBQFFKZOmlZadkQh/RmERAnxIAJ9Gn2U/YGxqgNVLciwLOf4j3pUmAwCdEgeh
Rfqouc+igLVzelUh2X18Bgs=
=yIPp
-----END PGP SIGNATURE-----
> Donal K. Fellows wrote:
>
>> Arnulf Wiedemann wrote:
>>> The problem is that for the new OO system there is a "my" needed in
>>> front of the call to some_class_method ( "my some_class_method Hello
>>> World" ).
>>>
>>> To not change the behaviour of the current OO implementation it would be
>>> enough to allow to add some resolver procs to an object. That might also
>>> be necessary for other oo extensions.
>>
>> If the resolver is added to the object's namespace, that should do the
>> trick.
>
> Would that also work if it is written in C and has a Tcl command to call
> it?
answering my own question: yes
>
>> In turn, the best way to do that would be to subclass the basic
>> oo::object and oo::class and attach the extra code in there. That
>> _should_ do the trick. (The 'my' is needed in the basic OO system
>> because methods are not actually standard Tcl commands.
>
> The resolver is just adding the "my" in front of the call if its within
> the appropriate context and the method is visible concerning Itcl's rules
> and adds an evaluation call for doing the stuff.
>
>> This is because
>> there's two sources of context data they need instead of the more
>> conventional single ClientData of a normal command; the other context
>> is the info about which object this is, etc.)
>
> OK, I will try that and report to you.
It is working
>
>>
>> I don't as yet know whether I've exposed all the right API needed in
>> order to enable the addition of constructors without contortions.
>> That's something I'd love feedback on - I'm far too close to the code
>> to see what's missing - so your message is very helpful.
>
> Another problem I have found out is, that Itcl has variables on a class
> base, not on an object base. Every class can have instance variables,
> which are not shared: "private variable somevariable". I think such a
> construct is not possible at the moment using the OO system.
>
> What also would be helpful if there would be a 3rd protection level, so
> one could have private, protected and public methods/variables. The rules
> are:
>
> private: only in the class they are defined
> protected: only in the class they are defined and in all derived classes
> (subclasses)
> public: visible from outside of the class/object
>
To make that a little bit more clear:
in Itcl you can have:
itcl::class cl1 {
private variable var1 123
protected variable var2 abc
public method cl1_show_var1and2 {} { puts "var1:$var1:"; puts "var2
$var2:" }
}
itcl::class cl2 {
inherit cl1
private variable var1 456
public method cl2_show_var1and2 {} { set var2 def; puts "var1:$var1:" ;
puts "var2:$var2:" }
}
# make an instance
cl2 obj1
obj1 cl1_show_var1and2
-> var1:123
-> var2:abc
obj1 cl2_show_var1and2
-> var1:456
-> var2:def
obj1 cl1_show_var1and2
-> var1:123
-> var2:def
Hope that helps.
Arnulf
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Rock on!
>
> Time for an Itcl 4.0, eh?
I will give it a try. Maybe I don't succeed, but it seems to be an
interesting area. Was only using Tcl/Itcl on the user side, will now have
to go to the developpers side (have few experience with Tcl's internals),
but ... :-).
Arnulf
Arnulf Wiedemann wrote:
> David Gravereaux wrote:
>
> Rock on!
>
> Time for an Itcl 4.0, eh?
>
>> I will give it a try. Maybe I don't succeed, but it seems to be an
>> interesting area. Was only using Tcl/Itcl on the user side, will now have
>> to go to the developpers side (have few experience with Tcl's internals),
>> but ... :-).
For some unknown reason, I'm the only Itcl developer left.. Chad and
Michael have disappeared. I did a massive amount of bug fixes and
worked on the sourceforge move-in around 2000 and they promoted me to
project "manager" of sorts..
Let me know your sourceforge ID, and I'll upgrade you to CVS write
permission and stuff.
Most likely you should work on code changes off on a branch.
- --
David Gravereaux <davy...@pobox.com>
[species:human; planet:earth,milkyway(western spiral arm),alpha sector]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
iD8DBQFFKsGalZadkQh/RmERAgOeAKCJHSuU1NpVtd5+1YyHbUTB8U+N6wCfbFRe
2FVxb2P6FRIlC3Klg0gu3QU=
=nF0C
-----END PGP SIGNATURE-----
Hello David,
thanks for the offer of joining, my user id on Sourceforge is 558925 or
wiede. I think it is to early to put somthing into cvs (or did your project
already move to svn?). I have to play around a little bit before beginning
with a real implementation.
Can I ask you some questions on how Itcl should behave in some cases? Maybe
it's better not to overflood c.l.t with that stuff. My email is
arnulf at wiedemann-pri.de.
Seeing the answers to my questions, I think there should perhaps be an
implementation of handling variables according to private/protected/public
protection level scheme eventually independent of Itcl, which could be
perhaps later on either added to a basic OO system or integrated into the
Tcl core to use if some "magic" is switched on (for example an environment
variable etc. or a call to a function with the namespace to use it or ...)
So it could be used from others besides Itcl (It must not depend on these
keywards private/protected/public). One could also use something like
"oo::define classname unexport variable somevar" etc. in a later add on to
the oo:: system.
I will dive into the Itcl implementation of variables and into the Tcl core
*LookupVar* functions and see what I can learn for such an implementation.
Concerning class hierarchies I think it should be possible to use one of the
TIPs 257 or 279 and the special calling possibility within Itcl methods not
using an object can be done using the Resolver trick already implemented in
Itcl, that I have tested already a liitle bit with the oo:: implementation.
Arnulf Wiedemann wrote:
> Can I ask you some questions on how Itcl should behave in some cases? Maybe
> it's better not to overflood c.l.t with that stuff. My email is
> arnulf at wiedemann-pri.de.
You can bother us Itcl folks over on the mailing list:
https://lists.sourceforge.net/lists/listinfo/incrtcl-users
Regarding the other stuff, I really don't have much of a clue. I'm just
a caretaker and not much more. I would need some time to actually
formulate an opinion.
- --
David Gravereaux <davy...@pobox.com>
[species:human; planet:earth,milkyway(western spiral arm),alpha sector]
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.2 (MingW32)
iD8DBQFFLD4slZadkQh/RmERAqkHAJ43nGZ0Z45Kvm84/Z8iFAw++A6QrQCdGmnB
a6zGWhWc77O9qA6Y7dKhE+g=
=2aJS
-----END PGP SIGNATURE-----