[perl #31292] [PATCH classes/unmanagedstruct.pmc] Don't Share Nested Structs Across Parents
# New Ticket Created by chromatic # Please include the string: [perl #31292] # in the subject line of all future correspondence about this issue. # URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31292 Hi there, This test case and patch demonstrates and fixes a problem where *Structs sharing initializers that contain structs end up sharing a single nested *Struct. I'm not convinced the behavior is completely correct. It breaks one other test -- perhaps it's worth copying the data from the initializer's struct to the PMC's internal struct. Still, the behavior with this patch is more correct than without. -- c Index: t/pmc/nci.t === RCS file: /cvs/public/parrot/t/pmc/nci.t,v retrieving revision 1.45 diff -u -u -r1.45 nci.t --- t/pmc/nci.t 10 Aug 2004 16:18:44 - 1.45 +++ t/pmc/nci.t 23 Aug 2004 06:38:09 - @@ -1335,6 +1335,102 @@ 3: 800 OUTPUT +output_is('CODE', 'OUTPUT', multiple structs with nested structs); +.include datatypes.pasm + new P30, .OrderedHash + set P30['y'], .DATATYPE_INT + push P30, 0 + push P30, 0 + + new P29, .ManagedStruct, P30 + + new P16, .OrderedHash + set P16['x'], .DATATYPE_INT + push P16, 0 + push P16, 0 + + set P16['nested'], .DATATYPE_STRUCT_PTR + set P30, P16[-1] + setprop P30, '_struct', P29 + push P16, 0 + push P16, 0 + + new P17, .ManagedStruct, P16 + set P29['y'], 200 + set P17['x'], 100 + + set I30, P17['x'] + set I16, P17['nested';'y'] + + print Old X: + print I30 + print \nOld Y: + print I16 + print \n + + loadlib P30, 'libnci' + dlfunc P18, P30, 'nci_v_pii', 'vpii' + + print First call\n + + set P5, P17 + set I5, 10 + set I6, 20 + set I0, 1 + set I1, 2 + set I2, 0 + set I3, 1 + set I4, 0 + set P0, P18 + savetop + invokecc + restoretop + + set P17, P17['nested'] + set I16, P17['y'] + print First kid Y: + print I16 + print \n + + new P16, .ManagedStruct, P16 + set P16['x'], 800 + set P16['nested';'y'], 400 + + print Second call\n + + set P5, P16 + set I5, 1 + set I6, 2 + set I0, 1 + set I1, 2 + set I2, 0 + set I3, 1 + set I4, 0 + set P0, P18 + savetop + invokecc + restoretop + + set P30, P16['nested'] + set I16, P17['y'] + + print First kid Y: + print I16 + print \nSecond kid Y: + set I16, P30['y'] + print I16 + print \n + end +CODE +Old X: 100 +Old Y: 0 +First call +First kid Y: 20 +Second call +First kid Y: 20 +Second kid Y: 2 +OUTPUT + } # SKIP 1; Index: classes/unmanagedstruct.pmc === RCS file: /cvs/public/parrot/classes/unmanagedstruct.pmc,v retrieving revision 1.46 diff -u -u -r1.46 unmanagedstruct.pmc --- classes/unmanagedstruct.pmc 12 Aug 2004 09:10:05 - 1.46 +++ classes/unmanagedstruct.pmc 23 Aug 2004 06:38:09 - @@ -574,6 +574,17 @@ count = 1; VTABLE_set_integer_keyed_int(interpreter, value, i+1, count); } + +if (type == enum_type_struct || type == enum_type_struct_ptr) +{ +PMC *nested = VTABLE_getprop(interpreter, type_pmc, +string_from_cstring(interpreter, _struct, 0)); + +PMC *clone = pmc_new(interpreter, nested-vtable-base_type); +VTABLE_set_pmc(interpreter, clone, PMC_pmc_val(nested)); +VTABLE_setprop(interpreter, type_pmc, +string_from_cstring(interpreter, _struct, 0), clone); +} if (offs = 0) { offs = toff = calc_align(interpreter, pmc, type_pmc, type, toff); VTABLE_set_integer_keyed_int(interpreter, value, i+2, offs);
Re: A thought for later -- POD tables
Aaron Sherman wrote: =table C$_ | C$x | Type of Match Implied | Matching Code =row Any | CodeC $ | scalar sub truth | match if C$x($_) That's (the above comments aside) the same thing, and as I said when Luke suggested it, it seems fine if that's the way we'd prefer to go. I do want to make sure that there's some way to associate a caption, though. HTML doesn't have a real caption concept, but many markup languages do. Yes it does. There's a CAPTION element for tables in HTML 4.01/XHTML 1: http://www.w3.org/TR/html4/struct/tables.html#h-11.2.2 Is the general consensus,then, that an C=-introduced form would be better? I do agree that we don't want the capability to nest tables, as that DOES break POD down into a presentation system, which it was never meant to be. So perhaps the balanced syntax is too misleading there. I like the =table =row form. Sufficient syntax for laying out simple tables without letting people do silly things.
Re: NCI and callback functions
Stephane Peiry wrote: g_return_val_if_fail (G_IS_OBJECT (gobject), 0); Fails here anyway I just dont see what could be wrong with the way parrot could be passing the user_data? gtk shouldn't make assumption on the user_data argument IMHO. Whats the difference between the way parrot calls this, and the way the C example is doing it? As the parrot example follows exactly the same steps as the C one. The C example had NULL as user_data. Stephane leo
Re: NCI and callback functions
Leopold Toetsch wrote: Stephane Peiry wrote: g_return_val_if_fail (G_IS_OBJECT (gobject), 0); Fails here gtk shouldn't make assumption on the user_data argument IMHO. I now tried calling g_cclosure_new_object() and g_signal_connect_closure() directly. Doesn't segfault anymore (at least, when you pass a String as user_data) But the return value of the first call is NULL, because of the same check, G_IS_OBJECT(gobject). The whole idea behind callbacks is, that there is a userdata argument that get's passed through transparently. GTK is taking a gobject only. So there is currently no way to use the existing callback scheme. *If* that is solved then the next problem is of course that by calling gtk_main() the GTK event loop is running. That means, while Parrot_callback_C() would get called, the callback fuction itself wouldn't get run because Parrot isn't executing any code at that point. Parrot is stuck in the NCI call to gtk_main(). leo
Re: [perl #31114] [PATCH] Dynext functions
Mattia Barbon [EMAIL PROTECTED] wrote: I am not sure about this patch. It splits part of Parrot_load_lib into a Parrot_init_lib(Interp, load_func_ptr, init_func_ptr) So its applied finally. Thanks, leo
Re: [perl #31292] [PATCH classes/unmanagedstruct.pmc] Don't Share Nested Structs Across Parents
chromatic (via RT) wrote: Hi there, This test case and patch demonstrates and fixes a problem where *Structs sharing initializers that contain structs end up sharing a single nested *Struct. I'm not convinced the behavior is completely correct. It breaks one other test I'd rather not have the cloning in the C code. If you don't reuse the nested structure descriptor, it's wasting resources. I think implementing the C clone vtable in unmanaged struct would be much cleaner. If you want to reuse a structure then clone it in the code. The question with C clone just is: how deep should it copy. This holds as well for arrays and hashes. Anyway, if it's a deep copy, then we probably would need freeze/thaw in the UnManagedStruct PMC. leo
Re: t/pmc/perlhash.t#20 failed
Luke Palmer wrote: And as I look at the code for that test: It looks bogus. Is a PerlHash supposed to accept an integer as a key? AFAIK yes. The test output to this one is: 4 Four is 0 Yep. See #31128 leo
[perl #31285] [PATCH] first step in implementing a SCons base build
# New Ticket Created by Matt Fowles # Please include the string: [perl #31285] # in the subject line of all future correspondence about this issue. # URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31285 All~ This patch is an early step in getting a scons based build system for parrot. Currently, it leaves the make system in place, the goal being to add a SCons system alongside the make system until the scons one is entirely ready. This patch allows scons to build foo.c and foo.dump files from foo.pmc. It will automatically detect dependencies between various PMC's and rebuild them as appropriate. Obviously this requires SCons to be installed on the system (and SCons requires Python). But since parrot can be built without it, I figured that this was a non-issue. If any one has a burning itch to implement other parts of this system, feel free to email me so we can collaborate. Have fun, Matt -- Computer Science is merely the post-Turing Decline of Formal Systems Theory. -??? --- /dev/null 2004-08-11 14:33:25.0 -0400 +++ SConstruct 2004-08-22 19:30:44.0 -0400 @@ -0,0 +1,2 @@ +SConscript([ 'build_tools/scons_tools/pmcEnv.py', + 'classes/SConscript']) --- /dev/null 2004-08-11 14:33:25.0 -0400 +++ classes/SConscript 2004-08-22 19:29:51.0 -0400 @@ -0,0 +1,24 @@ +import re + +Import('pmcEnv') + +env = pmcEnv.Copy() + +pmc_re = re.compile(r'\.pmc$') + +local = Dir('.') +pmcs = filter( lambda(x): pmc_re.search(x), map(str, local.all_children())) + +for p in pmcs: +dump = env.Dump(p) +c = env.PMC(p) +env.Depends(dump, p) +env.Depends(c, dump) +env.Depends(c, p) + + +# Tell Emacs that this is python +# Local Variables: +# mode:python +# End: + Index: MANIFEST RCS file: /cvs/public/parrot/MANIFEST,v retrieving revision 1.722 diff -u -r1.722 MANIFEST --- MANIFEST 20 Aug 2004 17:09:50 - 1.722 +++ MANIFEST 22 Aug 2004 23:52:04 - @@ -18,6 +18,7 @@ README.win32 [main]doc RELEASE_INSTRUCTIONS [] RESPONSIBLE_PARTIES [main]doc +SConstruct[] TODO [main]doc TODO.win32[main]doc VERSION [main]doc @@ -38,7 +39,9 @@ build_tools/ops2c.pl [devel] build_tools/ops2pm.pl [devel] build_tools/pbc2c.pl [devel] +build_tools/scons_tools/pmcEnv.py [] build_tools/vtable_h.pl [] +classes/SConscript[] classes/array.pmc [] classes/bigint.pmc[] classes/boolean.pmc [] --- /dev/null 2004-08-11 14:33:25.0 -0400 +++ build_tools/scons_tools/pmcEnv.py 2004-08-22 20:13:23.0 -0400 @@ -0,0 +1,33 @@ +import re +import string + +pmcEnv = Environment() + +bldDump = Builder( action = 'perl classes/pmc2c2.pl --dump $SOURCE', + suffix = '.dump', + src_suffix = '.pmc') + +bldC = Builder( action = 'perl classes/pmc2c2.pl --c --no-lines $SOURCE', + suffix = '.c', + src_suffix = '.pmc') + +pmc_re = re.compile(r'\.pmc$') +extends_re = re.compile(r'pmclass.*extends\s+(\w+)') + + +def PMC_scan(node, env, path): +contents = node.get_contents() +deps = map(lambda(x): string.lower(x)+.pmc, extends_re.findall(contents)) +if(deps == [] and str(node) != classes/default.pmc): + deps = [default.pmc] + deps +deps += map(lambda(x): pmc_re.sub(.dump,x), deps) +#print str(node), - , deps +return deps + +pmcScanner = Scanner(function = PMC_scan, skeys = ['.pmc']) + +pmcEnv.Append(SCANNERS = pmcScanner) +pmcEnv.Append( BUILDERS = {'Dump' : bldDump } ) +pmcEnv.Append( BUILDERS = {'PMC' : bldC } ) + +Export('pmcEnv')
Re: NCI and callback functions
Leopold Toetsch wrote: Leopold Toetsch wrote: Stephane Peiry wrote: g_return_val_if_fail (G_IS_OBJECT (gobject), 0); Fails here gtk shouldn't make assumption on the user_data argument IMHO. The whole idea behind callbacks is, that there is a userdata argument that get's passed through transparently. GTK is taking a gobject only. So there is currently no way to use the existing callback scheme. Can't you wrap what you want to pass in a GObject?
Re: Compile op with return values
At 11:03 PM -0700 8/21/04, Steve Fink wrote: I am experimenting with registering my own compiler for the regex language, but the usage is confusing. It seems that the intention is that compilers will return a code object that gets invoked, at which time it runs until it hits an Cend opcode. But what if I want to return some values from the compiled code? Here's what's supposed to happen. The compile op only compiles the code passed in, it doesn't execute it. The returned sub object represents the entire code chunk that was compiled, and likely ought to be immediately executed itself. As a perl example, the eval function should give code like: compiler = compreg Perl5 eval_pmc = compile compiler, my_source eval_pmc() though the eval_pmc() call ought to check and see if it got anything in return. This does mean that if you skip the invocation of the returned PMC that things may not happen. This is fine. And for many languages the returned PMC won't actually do anything at all when invoked. It's important to note that the returned PMC does *not* represent any particular sub in the source -- rather it represents the entire source module. So if the language was C, for example, the returned PMC wouldn't do anything since C doesn't allow you to have code outside functions. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: [PATCH] Re: [perl #31128] Infinite loop in key_string
At 10:48 AM +0200 8/21/04, Leopold Toetsch wrote: Steve Fink wrote: ... For PerlHash, P0[foo;3] seems to be interpreted as an iterator access? I hope there's some other way of indicating that. Yep, KEY_integer_FLAG used to indicate, get me the next key and is used by the iterator. But as your test shows its ambiguous. We are already allowing integers and plain PMCs as aggregate keys, so we can't use that flag for iterator too. We still have KEY_number_FLAG. It's unused. I can't imagine that we gonna index aggregates by floating point numbers[1]. So if no one hollers I'll reuse this flag for denoting iterator access for hashes. I'd rather not. I can see this happening for specialized arrays and slices, so lets leave it as is. If we need another flag, then we add another flag. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Character sorting and comparison
Comparison was the one thing left out of the charset API from earlier. So here's the API entry: INTVAL compare(STRING, STRING) Compares the two strings. Returns 1 if the left side is lexically greater, -1 if the right side is lexically greater, and 0 if they're the same. Currently this is in the charset vtable, but that might change later to allow locale overrides. (It'll be hidden behind the string.c API at least, so that'll be transparent to bytecode) -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Instantiation
I was thinking about the case where you use a module, only to define a class that you then instantiate like this: use Some::Module::That::Defines::A::Class; our Some::Module::That::Defines::A::Class $foo := new; and I keep thinking that that's too redundant. It's not so much that I want to syntax-golf it down, but there's just no reason to throw that type around twice, when what you really WANT to say is that module over there is a class, instantiate me one. So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; This would be handy to have for those lengthy setups of all of the objects you have to have lying around: uses CGI $cgi :threaded :persistent; uses Apache $server; uses MLDBM $shared_data :file('/var/www/cache/cgi-shared-data'); uses IO::CGI $input :cgi($cgi); uses MIME::Entity $message :input($input); ...etc... -- 781-324-3772 [EMAIL PROTECTED] http://www.ajs.com/~ajs
Re: Instantiation
Aaron Sherman skribis 2004-08-23 12:53 (-0400): use Some::Module::That::Defines::A::Class; our Some::Module::That::Defines::A::Class $foo := new; and I keep thinking that that's too redundant (...) So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; Maybe, but I'd like something like this better: #!/usr/bin/perl6 use Module::AutoLoader :except(rx/^ Baz\:\: /); my Foo::Bar$bar .= new; my Quux::Xyzzy $xyzzy .= new; my Baz::Blah $blah .= new; # error, because there is no Baz::Blah::new Perhaps something must be added to tell it *when* to load modules: at runtime or during compilation. It shouldn't be hard to implement this module yourself, should it not go into the standard distribution. Juerd
Progressively Overhauling Documentation
In [EMAIL PROTECTED], [EMAIL PROTECTED] (Aaron Sherman) wrote: This bit of POD made me think about POD's lack of tabular formatting, a common idiom in technical documentation. I know POD is still in the wings, as it were, but I wanted to say this before I forget /me flings coffee cup against the wall [no, not Larry!]. Perl is getting a major overhaul. POD is... well... now we have =COMMENT. If anything drastic is happening to POD, I've missed it, but if Perl can be made over, why not POD? Or rather, why not the concepts and attitudes pertaining to documentation in general, and documenting Perl code in particular? (Yes, one of the nifty things about POD is its simplicity, so maybe it should be left alone -- and something new added to the mix; after all, There Is More Than One Way To Document It.) Adding extra =head levels and =tables (and rudimentary support for tables sounds like a good idea to me) is evolutionary; all well and good, but surely there are some grand revolutions waiting to be instigated. One of the selling features (or one of the features that is always sold) of POD is that you can mix it with your code. Except nobody does, at least I can't recall that last time I saw a module that did that, and I don't think I've ever really done that myself. The POD usually sits in a lump at the end of the file. Having the documentation next to the code it describes means when you change your function, you can't as easily forget to update the docs, the way you would with a separate file. It's a terrific idea, but the user docs you typically get with a module don't necessarily match your functions that closely, or in the same order. I suppose one idea was that programmers' docs (like Input, Process, Output) would go in POD so that you when you printed out your code, you got something nice to look at instead of lots of lines of #blahblah. Except I never print out my code, not nowadays, not very often. So it's easier (both reading and writing) to just put a bunch of #comments in the code itself. OK, there's one non-incremental idea: documentation that you can write in one place and display in some completely different order. (Shades of literate programming!) And although there are good reasons for keeping the docs in the same file as the code, there are equal but opposite reasons to keep it separate (if it's all piled up at the end of the file anyway). What gets presented to the user as one page could be bits and pieces from all over the place. Another problem with plain old-fashioned documentation -- and no small influence on programmers' dislike of such, I wager -- is that you're always duplicating work: first you have to explain to the computer how to do something, then you have to explain it again to the user. Not conducive to laziness, impatience, and hubris. I don't know how much can be done about this, because computers and humans think in such different ways, but I have in mind things like Getopt::Declare. (Stuff like Pod::Usage probably fits in here somewhere, too.) Having a nice, compact way to declare sub signatures is good. Being able to document those signatures, not just nearby, but *simultaneously*, would be great. It saves a bit on typing (probably), a LOT on procrastination (probably -- I think the psychological aspects cannot be emphasised too much in the conventional wisdom that programmers are reluctant to document their work), and the impossibility of the docs getting out of sync with the code is priceless. Well, easier said than done. In the end, the answer might have to be Yeah, there are lots of brilliant things that *could* be done, but P6 and Parrot already take up so much effort that it ain't gonna happen -- unless you actually contribute something yourself, in which case Show Us the Code, mister! But hey, rousing a bit of rabble is easy, and there's always the possibility that someone really clever will come up with an idea that is brilliant *and* feasible. - David what's up, docs Green
Re: Progressively Overhauling Documentation
David Green skribis 2004-08-23 11:30 (-0600): One of the selling features (or one of the features that is always sold) of POD is that you can mix it with your code. Except nobody does, at least I can't recall that last time I saw a module that did that, and I don't think I've ever really done that myself. The POD usually sits in a lump at the end of the file. I'll consider inline documentation when POD can be inlined. But as long as =command paragraphs need to start in the first column, I'm not interested in this feature. Having a nice, compact way to declare sub signatures is good. Being able to document those signatures, not just nearby, but *simultaneously*, would be great. IMHO, with Perl 6's verbose signatures, it'd really help if POD could copy the signature literally. This is one small thing I do like about PHP documentation. I also think POD should be overhauled completely. I've been thinking about proposing something like: sub foo ( Foo::Bar$bar, Quux::Xyzzy $xyzzy, +$verbose, +$foo ) description { Calculates the foo-intersection of $bar and $xyzzy, optionally blah blah blah... } returns Array | undef { # real code here } which would get rendered as: foo (Foo::Bar $bar, Quux::Xyzzy $xyzzy, +$verbose, +$foo) returns Array | undef; Calculate the foo-intersection of $bar and $xyzzy, optionally blah blah blah... Having {} instead of would also please me. Especially if we can get {b:foo} instead of Bfoo. But I haven't really given this much thought. That's why I haven't proposed it yet. But since POD is a hot topic now anyway, let's see what everyone thinks about this. Juerd
Re: Progressively Overhauling Documentation
Juerd wrote: David Green skribis 2004-08-23 11:30 (-0600): One of the selling features (or one of the features that is always sold) of POD is that you can mix it with your code. Except nobody does, at least I can't recall that last time I saw a module that did that, and I don't think I've ever really done that myself. The POD usually sits in a lump at the end of the file. I'll consider inline documentation when POD can be inlined. But as long as =command paragraphs need to start in the first column, I'm not interested in this feature. What if we add Cdoc attribute that the execution compiler would discard, but POD compilers (and debuggers) could make use of? I believe that would even allow a particularly stringent corporate policy to create a flavor of 'strict' which required documentation of various classes of elements (though whether anyone would work there is another question...). But imagine debugging code, and being able to quickly see a comment on a variable you can't figure out. Juerd's sample would become: sub foo :doc(take an Foo::Bar, and foo it over.) ( Foo::Bar$bar:doc(what to foo up.), Quux::Xyzzy $xyzzy :doc(Xyzzy to foo bar with), +$verbose, +$foo } returns Array | undef { # real code here } -- Rod Adams
[perl #31302] NCI GC issues
# New Ticket Created by Dan Sugalski # Please include the string: [perl #31302] # in the subject line of all future correspondence about this issue. # URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=31302 Current CVS parrot looks to be losing track of NCI PMCs. Once a DOD run goes they get swept collected up, which is a Bad Thing. (Disabling DOD programmatically with the sweepoff op fixes things, as does the -G flag, but neither are particularly good as a long-term solution...) -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Progressively Overhauling Documentation
Rod Adams skribis 2004-08-23 13:16 (-0500): sub foo :doc(take an Foo::Bar, and foo it over.) ( Anything involving a string is not good for documentation, because in documenation it must be *easy* to add code examples. Besides that, () would make me want to put it all on one line, and that may be a little *too* concise for documentation. class Dog { sub bite ( Int $strength is validated { 0 $_ = 9 } # Do we have # something like this # yet? ) description { foo bar baz, demonstrated here: =verbatim { ... } In any case, {b:CAVE CANEM}. # Translated: beware of the dog. # And yes, that's a comment in POD, and should not be rendered. } { .mouth.open; .head.extend; .mouth.close $strength; } } Juerd
RE: Progressively Overhauling Documentation
unsubscribe -Original Message- From: Juerd [mailto:[EMAIL PROTECTED] Sent: Monday, August 23, 2004 12:01 PM To: Rod Adams Cc: [EMAIL PROTECTED] Subject: Re: Progressively Overhauling Documentation Rod Adams skribis 2004-08-23 13:16 (-0500): sub foo :doc(take an Foo::Bar, and foo it over.) ( Anything involving a string is not good for documentation, because in documenation it must be *easy* to add code examples. Besides that, () would make me want to put it all on one line, and that may be a little *too* concise for documentation. class Dog { sub bite ( Int $strength is validated { 0 $_ = 9 } # Do we have # something like this # yet? ) description { foo bar baz, demonstrated here: =verbatim { ... } In any case, {b:CAVE CANEM}. # Translated: beware of the dog. # And yes, that's a comment in POD, and should not be rendered. } { .mouth.open; .head.extend; .mouth.close $strength; } } Juerd
Re: Progressively Overhauling Documentation
Thalhammer, Jeffrey BGI SF skribis 2004-08-23 12:03 (-0700): unsubscribe It doesn't work that way. If I'm not mistaken, unsubscribing is done by sending mail to [EMAIL PROTECTED]. Also, you might want to consider using a sane e-mail program and some training in quoting :) Juerd
Re: Instantiation
So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; Well if the long name is the problem: use Some::Module::That::Defines::A::Class as Foo; my Foo $obj .= new; # OR # require Some::Module::That::Defines::A::Class; import Some::Module::That::Defines::A::Class as Foo; This seems to be more similar to what is done in other languages. You still have to write the class name repeatedly - but it does cut the typing. It does reduce the magic that is occuring behind the scenes (or at least redirects it to somewhere else). I guess Foo would be a full fledged class which inherits from Some::Module::That::Defines::A::Class. I doubt that it is optimal - but it does give a little bit of flexibility. Paul Seamons
Re: Return with no expression
On Fri, 20 Aug 2004 09:21:02 +0100, Matthew Walton [EMAIL PROTECTED] wrote: On 19 Aug 2004, at 18:04, Luke Palmer wrote: [...] my $num = $param == 0 ?? 0 : rand $param; my $num = $param == 0 ?? 0 :: rand $param; surely? a little off theme.. I wanna ask, could be there in perl6 any difficulties with recognizing C:: as part of C... ?? ... :: ... and C:: as module sigil? Does it involve some DWIM? Would we have mandatory space after C?? :: ? I didn't get perl6 syntax well yet, so if it's true, you can give better examples yourself..
Re: Instantiation
Aaron Sherman wrote: I was thinking about the case where you use a module, only to define a class that you then instantiate like this: use Some::Module::That::Defines::A::Class; our Some::Module::That::Defines::A::Class $foo := new; and I keep thinking that that's too redundant. It's not so much that I want to syntax-golf it down, but there's just no reason to throw that type around twice, when what you really WANT to say is that module over there is a class, instantiate me one. So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; syntax will be awful and there are a lot of guesses, but: macro uses($class, $var) is parsed(/(classname) (scalar)/) { use $class; our $class $var; } I suspect. It's probably not quite that simple, but I figured it was worth a shot. Hopefully the compiler would run through the result of the macro, parse it and compile it as normal so the Cuse would actually work. Okay okay, I just got a copy of Perl 6 and Parrot Essentials and I'm trying to learn stuff. I'm even ripping apart the compiler I wrote for my BSc final-year project so it generates working PIR instead of broken C.
Re: NCI and callback functions
On Mon, Aug 23, 2004 at 12:14:51PM +0200, Leopold Toetsch wrote: Leopold Toetsch wrote: Stephane Peiry wrote: g_return_val_if_fail (G_IS_OBJECT (gobject), 0); Fails here gtk shouldn't make assumption on the user_data argument IMHO. [...] call is NULL, because of the same check, G_IS_OBJECT(gobject). mh.. ok, this whole thing made me try the following, and that is actually sticking to what I do really understand about nci and function signatures for parrot. Currently the signature is 'lptpPi' dlfunc P2, P1, 'g_signal_connect_object', 'lptpPi' and Ive placed P in there for the user data mainly because of the example taken from the t/pmc/nct.t tests and I thaught that well.. that would do the right thing :) Now I would have otherwise written the function sig as 'lptppi' dlfunc P2, P1, 'g_signal_connect_object', 'lptppi' as thats what gtk really wants, a pointer to the user data, and for sure p will give it exactly that. Doing so, gtk doesnt complain anymore, it goes onto creating the window, the button, installing the callback (by calling this g_signal..) without problems and shows the window and button. So now gtk is happy but parrot isnt: if I hit the button, it goes onto calling callback in parrot, and he breaks with: Parrot VM: PANIC: callback_info doesn't look like a pointer! C file src/inter_cb.c, line 132 (as I understand it, by having p on the signature for the user data, gtk gets what it wants, a pointer to the user data, but parrot doesnt like it because once it gets it, it doesnt get it wrapped into a PMC? otoh, if P is used then its gtk not happy because it wants a pointer rather than a - pmc - struct?.. how wrong is this view?) *If* that is solved then the next problem is of course that by calling gtk_main() the GTK event loop is running. That means, while Parrot_callback_C() would get called, the callback fuction itself wouldn't get run because Parrot isn't executing any code at that point. Parrot is stuck in the NCI call to gtk_main(). mh.. thats was not the way I understood callbacks were implemented. I mean understood from this thread (*): [1] pdd16 states: Hand over control to the external library. IT IS IMPORTANT THAT THE INTERPRETER YOU ARE CALLING BACK INTO IS NOT ACTIVE WHEN THE CALLBACK IS MADE! As we don't know, when the callback is invoked, my scheme uses an event so that its safe to run the PASM code. that callbacks were indeed installed through an event (that is on its own thread) so that it wouldnt block nomatter what parrot would be doing at a given point (say it invoked some long running function in a lib :) unless there would be a lock on the user data itself. Otherwise, already thaught of actually unrolling the gtk_main function and have it handled/implemented within parrot directly (mainly gtk_main simply loops and waits on the gtk event queue). Or maybe run it in its own thread if the event threads are not enought? Thanks, Stephane (*) Subject: [CVS ci] approaching pdd16 callbacks http://groups.google.com/groups?q=callback+group:perl.perl6.internalshl=enlr=ie=UTF-8group=perl.perl6.internalsselm=4024E112.5030809%40toetsch.atrnum=3 PS.: attached the same test files, just using the new signature. # -- Gtk Button Example. .sub _gtkcallback print Hello\n .end .sub _main @MAIN .include glib.pasm .include gtk.pasm .local pmc window .local pmc button .local pmc callback .local pmc userdata .local NCI init init = global Gtk::gtk_init init(0) # -- create the window .local NCI w_new w_new = global Gtk::gtk_window_new window = w_new(0) # -- create the button .local NCI b_new b_new = global Gtk::gtk_button_new_with_label button = b_new(Parrot) # -- install callback? .local pmc cb_sub cb_sub = global _gtkcallback userdata = new Integer userdata = 42 callback = new_callback cb_sub, userdata, pU # -- function sig is 'lptppi', then we have: #P5 is the button #P6 the callback #P7 data we may to pass through. #S5 clicked #I5 is 0 # -- Uncomment this section to actually install the callback # -- (this segfaulst on my system) .local NCI sig_conn sig_conn = global Glib::g_signal_connect_object sig_conn(button, clicked, callback, userdata, 0) # -- Set the container. .local NCI cont_add cont_add = global Gtk::gtk_container_add cont_add(window, button) # -- show button .local NCI w_show w_show = global Gtk::gtk_widget_show w_show(button) # -- show window w_show(window) .local NCI g_main g_main = global Gtk::gtk_main g_main() end .end saveall loadlib P1, 'libgtk-x11-2.0' dlfunc P2, P1, 'gtk_init', 'vii' store_global 'Gtk::gtk_init', P2 dlfunc P2, P1, 'gtk_main', 'vv' store_global 'Gtk::gtk_main', P2 dlfunc P2, P1, 'gtk_widget_show', 'vp' store_global 'Gtk::gtk_widget_show', P2 dlfunc P2, P1, 'gtk_container_add', 'vpp' store_global 'Gtk::gtk_container_add', P2 dlfunc P2, P1,
NCI default changes for x86
Folks, A word of warning -- I've disabled the JIT's auto-generation of NCI function headers on x86 systems. This is partly in an attempt to track down problems I'm having with NCI calls segfaulting, and partly because I keep adding in new function definitions only to find that they don't work when I get things home and run 'em on my OS X box. (OS X doesn't autogenerate function headers) If you want this functionality back in, add in a --ccflags=add{-DCAN_BUILD_CALL_FRAMES} to your configure and you should be set. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Progressively Overhauling Documentation
At Mon, 23 Aug 2004 19:46:34 +0200, [EMAIL PROTECTED] (Juerd) wrote: I also think POD should be overhauled completely. I've been thinking about proposing something like: sub foo ( Foo::Bar$bar, Quux::Xyzzy $xyzzy, +$verbose, +$foo ) description { Calculates the foo-intersection of $bar and $xyzzy, optionally blah blah blah... } returns Array | undef { # real code here } which would get rendered as: foo (Foo::Bar $bar, Quux::Xyzzy $xyzzy, +$verbose, +$foo) returns Array | undef; Calculate the foo-intersection of $bar and $xyzzy, optionally blah blah blah... I also think something like this is a great idea -- I've been doing a lot of programming in Octave and Emacs Lisp, and the latter's generated documentation makes it possible to program what would otherwise be a completely baroque and unmanageable system. But I wouldn't go for the syntax you have above. Why not just do it with a property, then ship with a doc-generator that makes use of it? sub foo($x is rw, $y) is doc . Does some stuff, then frobs $x without mercy. . { # ... } /s
Re: Progressively Overhauling Documentation
OK, there's one non-incremental idea: documentation that you can write in one place and display in some completely different order. (Shades of literate programming!) And although there are good reasons for keeping the docs in the same file as the code, there are equal but opposite reasons to keep it separate (if it's all piled up at the end of the file anyway). What gets presented to the user as one page could be bits and pieces from all over the place. Literate Programming handles reordering by allowing you to specify a hirearchical number as part of each doc piece. This could be easily a dded to POD. Something like: =(1.2.1) begin ... just default any unspecified values to incrementing the last one. A simple POD processor could just ignore them and a fancy one could use them to reorder the section accordingly. -- Mark Biggar [EMAIL PROTECTED]
Re: Instantiation
Hello, Aaron Sherman wrote: I was thinking about the case where you use a module, only to define a class that you then instantiate like this: [ snip ] So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; is $foo implicitely declared as our or my (or state or temp)? IMHO it'd be better to be explicit: my $foo = uses Some::Module::That::Defines::A::Class; our $bar = uses Some::Module::That::Defines::A::Class; Or, requiring Cuse to return it's first argument (IIRC a Class object): my $qux = use(Some::Module::That::Defines::A::Class).new(...); If Cuse's argument is a Module object, Cuse should return the first class of that module. I like the Cuse(...).new(...) form the best, because it allows you to pass parameters to Cnew. Ingo Blechschmidt -- Linux, the choice of a GNU | Running Windows on a Pentium is like having generation on a dual AMD- | a brand new Porsche but only be able to Athlon!| drive backwards with the handbrake on. Encrypted mails preferred. | (Unknown source)
Re: Instantiation
At Mon, 23 Aug 2004 15:51:00 -0400, [EMAIL PROTECTED] (Aaron Sherman) wrote: On Mon, 2004-08-23 at 15:19, Paul Seamons wrote: So, I was wondering about a synonym, like: uses Some::Module::That::Defines::A::Class $foo; Well if the long name is the problem: use Some::Module::That::Defines::A::Class as Foo; No, like I said: this is not golf. I'm trying to remove an element of redundancy that I think obscures the meaning of a set of statements. Saying, use reallylongnameforamodulethathassomeclass as Foo; our Foo $bar := .new; Still has the same redundancy, it's just been hidden a bit. If use/instantiate is a common practice for certain kinds of library, then I think we should have a mechanism to perform that pair as a single step. How about making use a list operator returning the module's return value (== its last statement?)? Then you could do something like my $x = (use Some::Module::That::Defines::A::Class).new(blah); This leaves a bad taste in my mouth -- I think importing a module and instantiating its main class should remain separate -- but this looks like a painless way to get what you want without a separate function or keyword. /s
Re: Compile op with return values
Dan Sugalski wrote: At 11:03 PM -0700 8/21/04, Steve Fink wrote: I am experimenting with registering my own compiler for the regex language, but the usage is confusing. It seems that the intention is that compilers will return a code object that gets invoked, at which time it runs until it hits an Cend opcode. But what if I want to return some values from the compiled code? Here's what's supposed to happen. The compile op only compiles the code passed in, it doesn't execute it. The returned sub object represents the entire code chunk that was compiled, and likely ought to be immediately executed itself. As a perl example, the eval function should give code like: compiler = compreg Perl5 eval_pmc = compile compiler, my_source eval_pmc() though the eval_pmc() call ought to check and see if it got anything in return. This does mean that if you skip the invocation of the returned PMC that things may not happen. This is fine. And for many languages the returned PMC won't actually do anything at all when invoked. It's important to note that the returned PMC does *not* represent any particular sub in the source -- rather it represents the entire source module. So if the language was C, for example, the returned PMC wouldn't do anything since C doesn't allow you to have code outside functions. Could not variable initializers require code outside of subs to be executed even in C? The issue of elaboration (to borrow a word from the Ada world) always needs to be considered in cross language programming. Only one language can own main and some provision always needs to be made to invoke the outside-of-subs set-up code the other langauges need. This issues applies not only to eval but to things like loading dynamic libraries. The problems that leo and Stephane are having with gtk are related to this as well, i.e., it looks like parriot and Gtk are fighting over who is main. -- [EMAIL PROTECTED] [EMAIL PROTECTED]
Re: NCI and callback functions
mh.. guess P is an actuall pointer to PMC, in that case forget that part.. :) Stephane On Mon, Aug 23, 2004 at 11:15:03PM +0200, Stephane Peiry wrote: [signatures question gone] *If* that is solved then the next problem is of course that by calling gtk_main() the GTK event loop is running. That means, while Parrot_callback_C() would get called, the callback fuction itself wouldn't get run because Parrot isn't executing any code at that point. Parrot is stuck in the NCI call to gtk_main(). mh.. thats was not the way I understood callbacks were implemented. I mean understood from this thread (*): [1] pdd16 states: Hand over control to the external library. IT IS IMPORTANT THAT THE INTERPRETER YOU ARE CALLING BACK INTO IS NOT ACTIVE WHEN THE CALLBACK IS MADE! As we don't know, when the callback is invoked, my scheme uses an event so that its safe to run the PASM code. that callbacks were indeed installed through an event (that is on its own thread) so that it wouldnt block nomatter what parrot would be doing at a given point (say it invoked some long running function in a lib :) unless there would be a lock on the user data itself. Otherwise, already thaught of actually unrolling the gtk_main function and have it handled/implemented within parrot directly (mainly gtk_main simply loops and waits on the gtk event queue). Or maybe run it in its own thread if the event threads are not enought? Thanks, Stephane
Re: Compile op with return values
At 7:13 AM -0700 8/23/04, Mark A. Biggar wrote: Dan Sugalski wrote: At 11:03 PM -0700 8/21/04, Steve Fink wrote: I am experimenting with registering my own compiler for the regex language, but the usage is confusing. It seems that the intention is that compilers will return a code object that gets invoked, at which time it runs until it hits an Cend opcode. But what if I want to return some values from the compiled code? Here's what's supposed to happen. The compile op only compiles the code passed in, it doesn't execute it. The returned sub object represents the entire code chunk that was compiled, and likely ought to be immediately executed itself. As a perl example, the eval function should give code like: compiler = compreg Perl5 eval_pmc = compile compiler, my_source eval_pmc() though the eval_pmc() call ought to check and see if it got anything in return. This does mean that if you skip the invocation of the returned PMC that things may not happen. This is fine. And for many languages the returned PMC won't actually do anything at all when invoked. It's important to note that the returned PMC does *not* represent any particular sub in the source -- rather it represents the entire source module. So if the language was C, for example, the returned PMC wouldn't do anything since C doesn't allow you to have code outside functions. Could not variable initializers require code outside of subs to be executed even in C? Absolutely. The C compiler module can do whatever it likes when it compiles code -- it's certainly acceptable for it to run code as well. (Heck, there's nothing to stop you from having a compiler module which reformats your hard drive if you feed it Intercal) The returned PMC, which represents the entire compiled code module, can also do something when executed, and likely should. The issue of elaboration (to borrow a word from the Ada world) always needs to be considered in cross language programming. Only one language can own main and some provision always needs to be made to invoke the outside-of-subs set-up code the other langauges need. This issues applies not only to eval but to things like loading dynamic libraries. The problems that leo and Stephane are having with gtk are related to this as well, i.e., it looks like parriot and Gtk are fighting over who is main. Yeah, we've got to un-main ourselves better than we do. -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Return with no expression
Alexey Trofimenko wrote: On Fri, 20 Aug 2004 09:21:02 +0100, Matthew Walton [EMAIL PROTECTED] wrote: On 19 Aug 2004, at 18:04, Luke Palmer wrote: [...] my $num = $param == 0 ?? 0 : rand $param; my $num = $param == 0 ?? 0 :: rand $param; surely? a little off theme.. I wanna ask, could be there in perl6 any difficulties with recognizing C:: as part of C... ?? ... :: ... and C:: as module sigil? Does it involve some DWIM? Would we have mandatory space after C?? :: ? I didn't get perl6 syntax well yet, so if it's true, you can give better examples yourself.. I doubt that's a problem, as C:: as part of the ternary operator is only going to be found where an operator is expected, and C:: as part of a module name is only going to be found where an identifier is expected, so it's a matter of looking for different things in different places, I suspect. And if this message comes out with strange and stranger formatting, that's because Thunderbird's doing some very odd things in the compose window and I'm not entirely sure how it's going to come out.
Re: Return with no expression
Matthew Walton skribis 2004-08-23 23:12 (+0100): I doubt that's a problem, as C:: as part of the ternary operator is only going to be found where an operator is expected, and C:: as part of a module name is only going to be found where an identifier is expected, so it's a matter of looking for different things in different places, I suspect. Where :: (in a module name) can be used, an operator could have been used. How is $foo??Bar::Baz::Quux parsed? I hope it's an error, although some people aren't going to like mandatory whitespace around an already rather fat operator. Juerd
Re: Return with no expression
Juerd writes: Where :: (in a module name) can be used, an operator could have been used. How is $foo??Bar::Baz::Quux parsed? $foo ?? Bar::Baz::Quux; # error, :: expected Indeed, this is illegal: Bar::Baz :: Quux.new; No whitespace allowed. I hope it's an error, although some people aren't going to like mandatory whitespace around an already rather fat operator. It's only manditory where it would be misinterpreted as a package sigil/separator. $foo??split()::0; Ought to be fine, though: $foo??split::0; Would croak on you. Luke
Re: Progressively Overhauling Documentation
On Mon, 23 Aug 2004 [EMAIL PROTECTED] wrote: OK, there's one non-incremental idea: documentation that you can write in one place and display in some completely different order. (Shades of literate programming!) And although there are good reasons for keeping the docs in the same file as the code, there are equal but opposite reasons to keep it separate (if it's all piled up at the end of the file anyway). What gets presented to the user as one page could be bits and pieces from all over the place. Literate Programming handles reordering by allowing you to specify a hirearchical number as part of each doc piece. I am not sure I understand *why* you need reordering of documentation. Literate programming is useful because it reorders *code* while writing documentation in the intended order. Could somebody provide a concrete example of the need to reorder documentation? I was extensively using literate programming for the project I am working on. But after a while (7000 lines of p5 code, about 50 files) the cost of maintaining it seemed more than the gain even though I was heavily preprocessing the code to take the drudgery out, and I have come back to good ol' POD. I have come to believe that for short nasty pieces of code (implementing complicated algorithms) LP is a fantastic idea, but for larger systems that are not exactly imperative and have weird control flow (with hooks and such; or with an event loop of Tk), LP is no advantage. IMHO, for the few people who'd want to use LP, it would be easier and lazier to hack something like noweb to understand your annotations (perchance even understand POD :) ) than to make POD jump through hoops. --abhijit
Re: Instantiation
Sean O'Rourke [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] my $x = (use Some::Module::That::Defines::A::Class).new(blah); how about some variation on my $x = Some::Module::That::Defines::A::Class.AUTOLOAD.new(blah); Dave.
bidirectional iterators
There has been a lot of discussion in the other threads lately about iterators. I was wondering if there will be an easy way to create a bidirectional iterator? Toy example to show what I'm thinking: for(1..10) { next if /7/; # always skip 7 prev if 9 !rand 3; # occasionally backup and redo 8 print; } More significant example: class BigNum is Iterator:bi { has [EMAIL PROTECTED] is Iterator:bi; ...; method postfix:*=($arg) { my @temp is Iterator:bi; my $carry = 0; for ([EMAIL PROTECTED]:last_to_first) { my $num = $_ * $arg + $carry; my $val = $num % 10; $carry = int( $num / 10 ); unshift @temp, $val; # efficient because it's a bi Iter } [EMAIL PROTECTED] = @temp; } }; Sometimes an iterator cannot be bidirectional--for example, reading from STDIN--but that's fine; not all iterators need to be. And yes, if I want a linked list, I can use a module off the 6PAN, or write it myself, but that involves objects and methods. That's a lot of conceptual overhead for something that may be quite simple. --Dks -- [EMAIL PROTECTED]
Need some opinions on base behavior
Leo's been nudging me to get the behaviours of the basic types defined, so I'm working on updating PDD 17 with them. The unary behavior of the types is reasonably straightforward. What I'm puzzling over right now is the binary behavior. It's the edge cases that are troublesome, of course -- what to do on overflow, and what to do with fractional results. Fractions are an issue mainly with integer division -- in the case of int/int, should the result be an int, or a float of some sort? Overflow's an issue to some extent with addition and subtraction, but moreso with multiplication. Should the result be promoted to a larger type (either unconditionally, or on overflow), which one, and what counts as overflow? (Is it exceeding the limits of the type, or losing precision?) I'm up for some discussion on this one. I'm tempted to leave integer binary ops integers, binary ops with one or two floats a float, and binary ops with a bignum as a bignum and to heck with overflow, but I can see arguments for a more precise answer, as well as providing a way to specify whether you want accuracy or speed (potentially with or without throwing an exception where promotion'd otherwise take place and we don't). We could do them all, but... that seems more than a little excessive. Besides the MMD table entries, there'd be a lot of flag checking (or a *really* big set of MMD tables) which is sub-optimal. This'd be a good time to make cases, folks! -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk
Re: Need some opinions on base behavior
Dan~ I was originally going to say do them all or do the integer division/no overflow check option, but then something occurred to me. We already have I registers. If someone wants speed they should be using them anyway. If someone doesn't care about speed, but wants those semantics, their compiler can emit code of the form set I0, P0 set I1, P1 add I2, I0, I1 set P2, I2 and even then the code should not slow too much (I hope) Thus, I think that I will vote for int/int - float and int*int - [big]int What I vote against is float + float - int. I don't care if the result float happens to be an int, I have an unreasoning dislike of it. Also, if people are not satisfied with the options they can (and probably will) write their own PMCs to extend them. Actually that might be an argument for implementing everything, cause someone surely will so we might as well provide it. But I don't really like that, so I am sticking with my first answer. Matt On Mon, 23 Aug 2004 21:13:46 -0400, Dan Sugalski [EMAIL PROTECTED] wrote: Leo's been nudging me to get the behaviours of the basic types defined, so I'm working on updating PDD 17 with them. The unary behavior of the types is reasonably straightforward. What I'm puzzling over right now is the binary behavior. It's the edge cases that are troublesome, of course -- what to do on overflow, and what to do with fractional results. Fractions are an issue mainly with integer division -- in the case of int/int, should the result be an int, or a float of some sort? Overflow's an issue to some extent with addition and subtraction, but moreso with multiplication. Should the result be promoted to a larger type (either unconditionally, or on overflow), which one, and what counts as overflow? (Is it exceeding the limits of the type, or losing precision?) I'm up for some discussion on this one. I'm tempted to leave integer binary ops integers, binary ops with one or two floats a float, and binary ops with a bignum as a bignum and to heck with overflow, but I can see arguments for a more precise answer, as well as providing a way to specify whether you want accuracy or speed (potentially with or without throwing an exception where promotion'd otherwise take place and we don't). We could do them all, but... that seems more than a little excessive. Besides the MMD table entries, there'd be a lot of flag checking (or a *really* big set of MMD tables) which is sub-optimal. This'd be a good time to make cases, folks! -- Dan --it's like this--- Dan Sugalski even samurai [EMAIL PROTECTED] have teddy bears and even teddy bears get drunk -- Computer Science is merely the post-Turing Decline of Formal Systems Theory. -???
Re: Instantiation
Dave Whipp wrote: Sean O'Rourke [EMAIL PROTECTED] wrote in message news:[EMAIL PROTECTED] my $x = (use Some::Module::That::Defines::A::Class).new(blah); how about some variation on my $x = Some::Module::That::Defines::A::Class.AUTOLOAD.new(blah); Wow, that's pretty amazing... uh... I think I'd just prefer to do it the old fashioned way. If my suggestion was really that horrific, I withdraw the question.
Re: Return with no expression
I think I'd prefer that as well, since it has the advantage of not having to use the evil shift key. Though i don't think it stands out as much as it should. I hate to reply to my own message, but... How about $foo??split()!!0; for a touch of craziness. Or is !! not usable? Actually, just ignore this suggestion, I know it's a terrible one :)
Re: Return with no expression
Aaron Sherman writes: Luke Palmer wrote: $foo??split()::0; Ought to be fine Imagine the shock of the first guy who rezlizes he got the logic backwards and bug-fixes it to: $foo??0::split() ouch! Yeah, seriously. I mean, what a subtle bug! It would take him hours to figure out went wrong! Luke