From: Bram Geron <[EMAIL PROTECTED]> Date: Sat, 05 Jan 2008 23:38:57 +0100
Hi, Currently, argument passing is done using the same code as return value passing (with :flat and :slurpy stuff). But there's a small difference: argument passing can generate more errors than return value passing . . . It used to be that Parrot did not signal any such errors, because it did not know what the HLL signatures were. When Leo++ implemented the present arg/return passing scheme, the arg-count error was turned on (gingerly) by default, since that was deemed A Good Thing, but the return-count error was left off because it was feared (with reason) that too much code would break. . . . If you do $P0 = myfun(), where myfun returns two values, then the first value is stored in $P0 and that's it. This is wanted behaviour for a lot of languages, I think. A lesser known fact is probably that if myfun returns no values, then $P0 is unchanged. Hmm. This ought to be documented better. Very few languages want this, I think. For example, Common Lisp fills missing values with nil, and Perl with undef. Octave and Scheme seem to error. Are there languages with other behaviour? Scheme errors because returning multiple values *is* argument passing, and that's how argument passing in Scheme works. (And Schemers would gag on the inconsistency. ;-) Creating Octave/Scheme behaviour is easy. errorson .PARROT_ERRORS_RESULT_COUNT_FLAG Deceptively easy. The problem with this is that it affects all bytecode running in that interpreter, no matter what language it came from. This is going to break other languages' assumptions. The simplest thing I can imagine to create CL/Perl behavior is to initialize $P0 with nil/undef. But it Doesn't Feel Right(tm) to me doing this every time. What's your opinion? To receive values, the Kea-CL compiler generates code like this: . . . ($P42 :optional, $I42 :opt_flag) = $P44($P40) $P45 = constants[1] ## NIL if $I42 goto L1 $P42 = $P45 L1: . . . This is semi-robust w.r.t. PARROT_ERRORS_RESULT_COUNT_FLAG: If the flag is on, this call doesn't complain if $P44 returns zero values, and is insensitive to what Parrot does with $P42 in that case. On the other hand, it would fail if $P44 returned two or more values. Adding another "$P999 :slurpy" arg would fix that, but at the cost of allocating an array (usually empty) for each call -- which is why I don't bother. Better would be an ":ignored" keyword that skipped the slurp step without allocating anything. (Seems to me this was discussed at one point, but was not a priority.) Granted, it would be slicker to have a way to say "optional- defaulting-to-something" for all return values, but as you point out, different languages have different requirements for what that "something" should be. So I think the current mechanism for defaulting is acceptable; there are more important fish to fry. (BTW, initializing $P42 with NIL in advance would require fewer instructions, but would break if $P42 were a lexical variable that was used by the $P44 sub; it would expect to see the original value before assignment. It's a good idea for optimization, though.) Other question: what should compilers do for languages that don't support multiple values? If such a language allows calling functions from other languages, I can imagine obscure bugs appearing. Cheers, Bram Geron Good point. Perhaps we need PIR syntax like: () = $P44($P40) to require exactly zero values, and ($P42 :required) = $P44($P40) to require exactly one? In any case, I would argue that such things are lexically determined, usually by the language, and would ditch PARROT_ERRORS_RESULT_COUNT_FLAG entirely in favor of PIR syntax at the point of call to give each compiler complete control. This, IMHO, would be worth the trouble. -- Bob Rogers http://rgrjr.dyndns.org/