[perl #28393] [PATCH] Tcl pmcs
# New Ticket Created by Will Coleda # Please include the string: [perl #28393] # in the subject line of all future correspondence about this issue. # http://rt.perl.org:80/rt3/Ticket/Display.html?id=28393 > Attached, find a .tgz that can be exploded in the top level of parrot which creates the abstract pmc "tclobject", with children "TclString", "TclInt", "TclFloat", and container pmcs "TclList" (an array) and "TclArray" (a hash). Tcl{String,Int,Float} work like their Perl counterparts, and, to use tcl parlance, "shimmer" to the appropriate type as necessary. This was basically a cut and paste job from the various Perl versions, so there will be future patches (and, er, tests - someone let me know if the tests belong in languages/tcl or if I should follow perl's lead and put them in parrot's test dir) to these classes to eventually make them even more tcl-ish (including automatic conversion between the array and the string), but this'll let me rip out all references to Perl in languages/tcl, which is a good thing. The biggest thing which I tripped over here was that Array.pmc uses PerlUndef to shimmer a few of the types. So, when I did: $P1 = new TclList $P1[0] = "eek" $P2 = $P1[0] $S0 = typeof $P2 print $S0 I'd get PerlString, because of inherited methods from Array.pmc. I just had to override those methods. (basically a cut and paste-o, changing the PerlUndef to a TclString, since that shimmers to the right types.) I now have commit privs to languages/tcl (thanks!), so I have some local updates that are waiting on this getting in. A re-configure/make is necessary to be able to use the Tcl* pmcs if you're feeling adventurous. tcl_pmc.tar.gz Description: GNU Zip compressed data -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > Attached, find a .tgz that can be exploded in the top level of parrot > which creates the abstract pmc "tclobject", with children "TclString", > "TclInt", "TclFloat", and container pmcs "TclList" (an array) and > "TclArray" (a hash). Can we put these PMCs into dynclasses? I don't think that Parrot core should contain all possible PMCs of all supported languages. OTOH we should have some support for selecting $LANG PMCs at compile time (and no, I don't cosider the current manual selection of classes as support:) > A re-configure/make is necessary to be able to use the Tcl* pmcs if > you're feeling adventurous. Can you try it with dynclasses? leo
Re: [perl #28393] [PATCH] Tcl pmcs
"They tried and failed?" "No, they tried and died." Ok, it's not that bad, but it doesn't seem to work. I moved the .pmcs (same files in previous attachment) over to ./dnyclasses, updated the Makefile as directed in dynclasses/README. To undo their previous inclusion, I did a make realclean, config, and make. After that, I see the following behavior: bash-2.05a$ ./parrot dynclasses/dynfoo.pasm open result was Access (5) for filename [foo] open result was Access (5) for filename [foo.dylib] open result was Access (5) for filename [foo] open result was Access (5) for filename [foo.dylib] ok 1 54 ok 2 42 bash-2.05a$ cat joe.imc .sub main $P1 = loadlib "tclstring" end .end bash-2.05a$ ./parrot joe.imc open result was Access (5) for filename [tclstring] open result was Access (5) for filename [tclstring.dylib] open result was Access (5) for filename [runtime/parrot/dynext/tclstring] Couldn't load 'runtime/parrot/dynext/tclstring': unknow reason open result was Access (5) for filename [tclstring] open result was Access (5) for filename [tclstring.dylib] open result was Access (5) for filename [runtime/parrot/dynext/tclstring] Couldn't load 'runtime/parrot/dynext/tclstring': unknow reason So... it's finding the lib (finally) at "runtime/parrot/dynext/tclstring.dylib" - but couldn't load it. The foo load seems to work fine, though. What next? And, are we going to move Perl* pmcs into dynclasses? I'd hate for them to bloat my parrot executable when running Tcl. =-) On Friday, April 9, 2004, at 03:39 AM, Leopold Toetsch wrote: Will Coleda <[EMAIL PROTECTED]> wrote: Attached, find a .tgz that can be exploded in the top level of parrot which creates the abstract pmc "tclobject", with children "TclString", "TclInt", "TclFloat", and container pmcs "TclList" (an array) and "TclArray" (a hash). Can we put these PMCs into dynclasses? I don't think that Parrot core should contain all possible PMCs of all supported languages. OTOH we should have some support for selecting $LANG PMCs at compile time (and no, I don't cosider the current manual selection of classes as support:) A re-configure/make is necessary to be able to use the Tcl* pmcs if you're feeling adventurous. Can you try it with dynclasses? leo -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > "They tried and failed?" > "No, they tried and died." > Ok, it's not that bad, but it doesn't seem to work. I moved the .pmcs > (same files in previous attachment) over to ./dnyclasses, updated the > Makefile as directed in dynclasses/README. You have to modify the PMCs a bit. The class enums are generated at load time. You must have had compile errors during $ make -C dynclasses clean all You need basically (in tclstring.pmc): #define enum_class_TclString -1 and some code in tclobject.morph to get at the real class enum. leo
Re: [perl #28393] [PATCH] Tcl pmcs
Ok. some progress, but still not happy. I don't understand what enum_class_TclString is doing in Parrot_TclString_class_init(Parrot_Interp interp, int entry) { struct _vtable temp_base_vtable = { NULL, /* package */ enum_class_TclString, /* base_type */ If I'm being dynamically generated, and I'm supposed to use the real values when morphing - what purpose does this serve? is it just a placeholder? And if so, why not just automatically gen it with -1 to avoid this issue? Or is this base_type used elsewhere... in which case does it have to be unique? across ALL dynamic pmcs? (and, if so, how do we insure that) That said, I still can't get the dynclasses to work properly. Here's my latest attempt. I can apparently load "tclobject", which is an abstract pmc used for morphing (and therefore does me no good at the PIR level), but if I try to load any of the real libraries, like "tclstring", it fails, again with the "unknown error" tclpmc.tar.gz Description: GNU Zip compressed data bash-2.05a$ cat dynfoo.imc .sub main loadlib $P2, "tclobject" $P2 = getprop "_filename", $P2 print "_filename:" print $P2 print "\n" $P2 = getprop "_ro", $P2 print "_ro:" print $P2 print "\n" loadlib $P2, "tclstring" $P2 = getprop "_filename", $P2 print "_filename:" print $P2 print "\n" $P2 = getprop "_ro", $P2 print "_ro:" print $P2 print "\n" end .end bash-2.05a$ ./parrot dynfoo.imc Couldn't load 'runtime/parrot/dynext/tclstring': unknow reason _filename:runtime/parrot/dynext/tclobject.dylib _ro: Couldn't load 'runtime/parrot/dynext/tclstring': unknow reason Null PMC access in getprop()bash-2.05a$ ls -l runtime/parrot/dynext/ total 344 drwxr-xr-x 5 coke staff170 Mar 18 00:10 CVS -rw-r--r-- 1 coke staff 53 Oct 24 05:37 README -rw-r--r-- 1 coke staff 18004 Apr 11 13:58 foo.dylib -rw-r--r-- 1 coke staff 18340 Apr 11 13:58 subproxy.dylib -rw-r--r-- 1 coke staff 27016 Apr 11 13:59 tclarray.dylib -rw-r--r-- 1 coke staff 22364 Apr 11 13:59 tclfloat.dylib -rw-r--r-- 1 coke staff 18016 Apr 11 13:59 tclint.dylib -rw-r--r-- 1 coke staff 22920 Apr 11 13:59 tcllist.dylib -rw-r--r-- 1 coke staff 8808 Apr 11 13:58 tclobject.dylib -rw-r--r-- 1 coke staff 18300 Apr 11 13:58 tclstring.dylib On Sunday, April 11, 2004, at 06:38 AM, Leopold Toetsch wrote: Will Coleda <[EMAIL PROTECTED]> wrote: "They tried and failed?" "No, they tried and died." Ok, it's not that bad, but it doesn't seem to work. I moved the .pmcs (same files in previous attachment) over to ./dnyclasses, updated the Makefile as directed in dynclasses/README. You have to modify the PMCs a bit. The class enums are generated at load time. You must have had compile errors during $ make -C dynclasses clean all You need basically (in tclstring.pmc): #define enum_class_TclString -1 and some code in tclobject.morph to get at the real class enum. leo -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > I don't understand what enum_class_TclString is doing in > Parrot_TclString_class_init(Parrot_Interp interp, int entry) > { > struct _vtable temp_base_vtable = { > NULL, /* package */ > enum_class_TclString, /* base_type */ > If I'm being dynamically generated, and I'm supposed to use the real > values when morphing - what purpose does this serve? is it just a > placeholder? On compilation of the C file C is a placeholder. Static classes have these enums in F, which is autogenerated by Configure. Dynamically loaded PMCs don't have an entry in that file, so there isn't any static enum_class_xxx. To make the code compile, a dummy define is (currently) necessary that makes the compiler happy. During loading of the dynamic class vtable->base_type is filled with the correct enum value. > ... And if so, why not just automatically gen it with -1 to > avoid this issue? No problem, patches welcome that include this line for the dynamic case. > ... Or is this base_type used elsewhere... in which case > does it have to be unique? across ALL dynamic pmcs? (and, if so, how do > we insure that) It's unique across the whole parrot process. This is assured by the PMC registration code. But it of course depends on load order of dynamic classes. Hope that this helps a bit. leo
Re: [perl #28393] [PATCH] Tcl pmcs
Well, it helps me understand the process a bit, ja. (Adding info to dynclasses/README in my local copy as I pick it up on list) I'm still baffled as to why my copy of, say, "TclString" is now compiling happily but failing to be loadable. (as opposed to "tclobject", which *is* loadable, but is not instatiable, and therefore much less interesting. =-) On Sunday, April 11, 2004, at 03:27 PM, Leopold Toetsch wrote: Will Coleda <[EMAIL PROTECTED]> wrote: I don't understand what enum_class_TclString is doing in Parrot_TclString_class_init(Parrot_Interp interp, int entry) { struct _vtable temp_base_vtable = { NULL, /* package */ enum_class_TclString, /* base_type */ If I'm being dynamically generated, and I'm supposed to use the real values when morphing - what purpose does this serve? is it just a placeholder? On compilation of the C file C is a placeholder. Static classes have these enums in F, which is autogenerated by Configure. Dynamically loaded PMCs don't have an entry in that file, so there isn't any static enum_class_xxx. To make the code compile, a dummy define is (currently) necessary that makes the compiler happy. During loading of the dynamic class vtable->base_type is filled with the correct enum value. ... And if so, why not just automatically gen it with -1 to avoid this issue? No problem, patches welcome that include this line for the dynamic case. ... Or is this base_type used elsewhere... in which case does it have to be unique? across ALL dynamic pmcs? (and, if so, how do we insure that) It's unique across the whole parrot process. This is assured by the PMC registration code. But it of course depends on load order of dynamic classes. Hope that this helps a bit. leo -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Ahhh.. Some additional debug output shows dyld: ./parrot Undefined symbols: _Parrot_tclobject_morph _Parrot_tclobject_set_pmc When trying to dynload, e.g. "tclint". If I look in tclobject.c, I see: Parrot_tclobject_morph(Parrot_Interp interpreter, PMC* pmc, INTVAL type) and Parrot_tclobject_set_pmc(Parrot_Interp interpreter, PMC* pmc, PMC* value) ... Any clues? On Sunday, April 11, 2004, at 06:04 PM, Will Coleda wrote: Well, it helps me understand the process a bit, ja. (Adding info to dynclasses/README in my local copy as I pick it up on list) I'm still baffled as to why my copy of, say, "TclString" is now compiling happily but failing to be loadable. (as opposed to "tclobject", which *is* loadable, but is not instatiable, and therefore much less interesting. =-) On Sunday, April 11, 2004, at 03:27 PM, Leopold Toetsch wrote: Will Coleda <[EMAIL PROTECTED]> wrote: I don't understand what enum_class_TclString is doing in Parrot_TclString_class_init(Parrot_Interp interp, int entry) { struct _vtable temp_base_vtable = { NULL, /* package */ enum_class_TclString, /* base_type */ If I'm being dynamically generated, and I'm supposed to use the real values when morphing - what purpose does this serve? is it just a placeholder? On compilation of the C file C is a placeholder. Static classes have these enums in F, which is autogenerated by Configure. Dynamically loaded PMCs don't have an entry in that file, so there isn't any static enum_class_xxx. To make the code compile, a dummy define is (currently) necessary that makes the compiler happy. During loading of the dynamic class vtable->base_type is filled with the correct enum value. ... And if so, why not just automatically gen it with -1 to avoid this issue? No problem, patches welcome that include this line for the dynamic case. ... Or is this base_type used elsewhere... in which case does it have to be unique? across ALL dynamic pmcs? (and, if so, how do we insure that) It's unique across the whole parrot process. This is assured by the PMC registration code. But it of course depends on load order of dynamic classes. Hope that this helps a bit. leo -- Will "Coke" Coledawill at coleda dot com -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > dyld: ./parrot Undefined symbols: > _Parrot_tclobject_morph > _Parrot_tclobject_set_pmc Ah yes. That's ugly. So here we go: 0) The PMCs were pre-ICU. I've adapted them. Should I check it in or send it back to you? 1) dynamic PMCs need a "dynpmc" flag on the class definition line. This causes the PMC compiler to add additional code for dynamic loading: pmclass TclString extends tclobject dynpmc { 2) Nasty dependencies. I got around that by changing the Makefile like so: tclobject$(SO) : tclobject.c $(LD) $(LD_SHARED) $(LD_SHARED_FLAGS) $(LDFLAGS) -Wl,-E -o $@ \ -I../include -I../classes \ -L../blib/lib -lparrot $< $(PERL) -MFile::Copy=cp -e 'cp q|$@|, q|../runtime/parrot/dynext/$@|' cd ../runtime/parrot/dynext; ln -sf tclobject.so libtclobject.so %$(SO) : %.c $(LD) $(LD_SHARED) $(LD_SHARED_FLAGS) $(LDFLAGS) -Wl,-E -o $@ \ -I../include -I../classes \ -L../blib/lib -lparrot -L../runtime/parrot/dynext \ -ltclobject $< $(PERL) -MFile::Copy=cp -e 'cp q|$@|, q|../runtime/parrot/dynext/$@ (and disabling non-tcl shared classes for now) That is for all tcl* but tclobject libtclobject.so is added as a library. This might also need the LD_LIBRARY_PATH to contain F. I don't know how we do that platform independend. It might be simpler to have a utility that copies all tcl*.c together into one and chains the Parrot_lib__load() functions. So only one shared lib would be loaded that registers all classes. Should be a rather simple script. E.g. merge-classes -o tcl-all.c tclobject.c tclstring.c ... Then compile and loadlib only the tcl-all. This would need a Parrot_lib_tcl-all_load() function that calls _load() for all contained PMCs. 3) For now $ cat tcl.pasm loadlib P10, "tclobject" print "ok 1\n" loadlib P11, "tclstring" print "ok 2\n" new P1, .TclString set P1, "ok 3\n" set S1, P1 print S1 end $ parrot tcl.pasm ok 1 ok 2 ok 3 leo
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > Attached, find a .tgz that can be exploded in the top level of parrot > which creates the abstract pmc "tclobject", with children "TclString", > "TclInt", "TclFloat", and container pmcs "TclList" (an array) and > "TclArray" (a hash). Applied now, slightly modified for dynclasses and with string-related adaptions due to API changes. leo
Re: [perl #28393] [PATCH] Tcl pmcs
Did the makefile change make it in? On Monday, April 12, 2004, at 04:57 AM, Leopold Toetsch wrote: Will Coleda <[EMAIL PROTECTED]> wrote: dyld: ./parrot Undefined symbols: _Parrot_tclobject_morph _Parrot_tclobject_set_pmc Ah yes. That's ugly. So here we go: 0) The PMCs were pre-ICU. I've adapted them. Should I check it in or send it back to you? 1) dynamic PMCs need a "dynpmc" flag on the class definition line. This causes the PMC compiler to add additional code for dynamic loading: pmclass TclString extends tclobject dynpmc { 2) Nasty dependencies. I got around that by changing the Makefile like so: tclobject$(SO) : tclobject.c $(LD) $(LD_SHARED) $(LD_SHARED_FLAGS) $(LDFLAGS) -Wl,-E -o $@ \ -I../include -I../classes \ -L../blib/lib -lparrot $< $(PERL) -MFile::Copy=cp -e 'cp q|$@|, q|../runtime/parrot/dynext/$@|' cd ../runtime/parrot/dynext; ln -sf tclobject.so libtclobject.so %$(SO) : %.c $(LD) $(LD_SHARED) $(LD_SHARED_FLAGS) $(LDFLAGS) -Wl,-E -o $@ \ -I../include -I../classes \ -L../blib/lib -lparrot -L../runtime/parrot/dynext \ -ltclobject $< $(PERL) -MFile::Copy=cp -e 'cp q|$@|, q|../runtime/parrot/dynext/$@ (and disabling non-tcl shared classes for now) That is for all tcl* but tclobject libtclobject.so is added as a library. This might also need the LD_LIBRARY_PATH to contain F. I don't know how we do that platform independend. It might be simpler to have a utility that copies all tcl*.c together into one and chains the Parrot_lib__load() functions. So only one shared lib would be loaded that registers all classes. Should be a rather simple script. E.g. merge-classes -o tcl-all.c tclobject.c tclstring.c ... Then compile and loadlib only the tcl-all. This would need a Parrot_lib_tcl-all_load() function that calls _load() for all contained PMCs. 3) For now $ cat tcl.pasm loadlib P10, "tclobject" print "ok 1\n" loadlib P11, "tclstring" print "ok 2\n" new P1, .TclString set P1, "ok 3\n" set S1, P1 print S1 end $ parrot tcl.pasm ok 1 ok 2 ok 3 leo -- Will "Coke" Coledawill at coleda dot com
Re: [perl #28393] [PATCH] Tcl pmcs
Will Coleda <[EMAIL PROTECTED]> wrote: > Did the makefile change make it in? Not the hacks to get it running. As said the way to go is to concatenate the sources and chain the loadlib _load() functions. This has two advantages: no platform dependent linker troubles to resolve symbols of multiple shared libs, and less resource usage for library loading. leo