Re: No Cpow op with PMC arguments?

2004-11-04 Thread Leopold Toetsch
Sam Ruby wrote:
This omission seems odd.  Was this intentional?
A single pow_p_p_p op backed by a (non-MMD) vtable entry would make it 
easier to support code like the following:
Well, Python has a pow vtable slot. And it should be MMD.
Patches welcome,
leo


Re: Closures and subs

2004-11-04 Thread Leopold Toetsch
Klaas-Jan Stol [EMAIL PROTECTED] wrote:
 Hello,

 I've been playing with closures and subs but I have a little bit of
 trouble with those.

 newsub $P0, .Closure, _foo
 $P0(q)
 newsub $P0, .Closure, _foo
 $P0(q)

Closures have to be distinct.


leo


Re: [PATCH] [resend] support of uniline yield/return

2004-11-04 Thread Leopold Toetsch
Stéphane Payrard wrote:
My previous mail to [EMAIL PROTECTED] did not seem to
make it. So the resend with many recipients.
This is the patch to support the uniline yield/return we talked 2
weeks ago. I know that Leo advocate to separate the
implementation of PASM and PIR. By retailoring the grammar and
the code such patches paves the way for such a separation.
Thanks, applied.
leo


Re: Solicitation of Ideas for Performance Statistics and Graphs

2004-11-04 Thread Leopold Toetsch
Joshua Gatcomb [EMAIL PROTECTED] wrote:

 If you would like to see any of these ideas
 implemented, or you have some of your own - please
 respond to this on the list.

I've amother one. Parrot has some internal settings and tweakable magic
constants, mainly all inside the garbage collector. It would be great,
if some of these settings could be compared.

E.g.

  # bench.config

  [ Default ]   # label for config section / graph

  [ IMS GC ]# incremental MS GC

  # file # subst to turn config on
  include/parrot/settings.h  s/(PARROT_GC_MS)\s+1/$1  0/

  # next setting, either based on previous or on default

Now instead of an overlay graph of unoptimized/optimized/non-JIT/JIT
(which isn't utterly useful) I'd like to see a comparison of the given
configurations, optimized build only.

WRT parrot run-options: there is a -Ot switch, which should enable the
fastest runtime options available on that machine.

 Cheers
 Joshua Gatcomb

leo


Re: [PATCH] dynclass build

2004-11-04 Thread Leopold Toetsch
Sam Ruby [EMAIL PROTECTED] wrote:

 Attached patch makes building in the dynclass ghetto a bit less
 inhospitable...

Thanks, applied.
leo


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Jeff Clites
On Nov 3, 2004, at 8:09 AM, Dan Sugalski wrote:
At 11:04 AM -0500 11/3/04, Sam Ruby wrote:

A single pow_p_p_p op backed by a (non-MMD) vtable entry would make 
it easier to support code like the following:

  def f(x): return x**3
  print f(3), f(2.5)
Yeah, it would. I know I'm going to regret asking, but... any reason 
*not* to make it MMD? (Though I have no idea what happens if you 
square a matrix)
I feel like we have op-itis and vtable-itis. I would think that rather 
than a pow_p_p_p, you'd compile x**y as something like:

set N0, P0
set N1, P1
pow N2, N0, N1
new P2, .PythonNumber
assign P2, N2
I.e., PMCs don't inherently exponentiate--numbers do, and you can 
exponentiate PMCs by numberizing them, exponentiating, and creating a 
PMC with the result.

Or, if we must have an op, implement it something like this (without 
needing a new vtable entry, or MMD):

inline op pow(out PMC, in PMC, in PMC) :base_core {
  $1 = pmc_new(interpreter, $2-vtable-type(interpreter, $2));
  $1-vtable-set_number_native(interpreter, $1,
 pow( $2-vtable-get_number(interpreter, $2),
 $3-vtable-get_number(interpreter, $3)))
  goto NEXT();
}
Those would probably JIT to about the same thing, given register 
mapping.

This is the viewpoint that pow() isn't a fundamental operation that 
makes sense for all types; it's a numeric operation, which can be 
extended in a straighforward manner to types which know how to 
represent themselves as numbers. (e.g., it's gibberish to raise a 
ManagedStruct to a ParrotIO power, except that you can stretch and 
interpret such a thing as just implicit num-ification of the 
arguments.)

JEff


Re: Closures and subs

2004-11-04 Thread Klaas-Jan Stol
Leopold Toetsch wrote:
Klaas-Jan Stol [EMAIL PROTECTED] wrote:
Hello,

I've been playing with closures and subs but I have a little bit of
trouble with those.
newsub $P0, .Closure, _foo
$P0(q)
newsub $P0, .Closure, _foo
$P0(q)
Closures have to be distinct.
leo

Thanks for your quick reactions.
Indeed, doing
$P0(q)
works ok. I'm a bit confused by syntax then (but I think it makes sense 
now, if IMCC sees the (, it is expecting args I guess)

In the mean time, I wrote another example for closures (maybe I should 
collect these in a HOWTO document :-)
(This one *is* working, however, again I don't understand why some 
things have to be done in a particular way)

First, I show the Lua code:
function newCounter ()
 local i = 0
 return function ()   -- anonymous function
   i = i + 1
   return i
 end
end
   
c1 = newCounter()
print(c1())  -- 1
print(c1())  -- 2

This is the translation (and it works! :-)
.sub _newcounter
   new_pad 0
   # local i = 0
   .local pmc i
   i = new .PerlInt
   i = 0
   store_lex -1, i, i
   # create closure of function to return
   .local pmc clos
   newsub clos, .Closure, _function
   # why should I do this? (should I?) .return clos does not work 
(then it's whining about SArray again)
   P5 = clos

.end
.sub _function
   # i = i + 1
   .local pmc j
   find_lex j, i
   j = j + 1
   print j
   store_lex -1, j, j
   # return i
   .return j 
.end

.sub _main @MAIN
   # c1 = newcounter()
   .local pmc c1
   c1 = _newcounter()
  
   # print(c1())   Prints 1
   .local pmc i   
   i = c1()
   print i
   print \n

   # print(c1())   Prints 2
   i = c1()
   print i
   print \n
   # print(c1())   Prints 3
   i = c1()
   print i
   print \n
   end
.end
So, this one works. I guess my question concerns syntax: why doesn't 
.return clos in newclosure() work?

Klaas-Jan


Re: Closures and subs

2004-11-04 Thread Luke Palmer
I haven't written PIR in a while, and I'm not terribly familiar with the
new changes, but I'll make some guesses.

Klaas-Jan Stol writes:
 function main()
   
local p = 123;   
local q = 345;
 
foo(q);
foo(q);
 
function foo(a) # nested function, it does have access to p in main
   print(p);
   p = p + p;
 
   print(typeof(a));
   print(a);
end
 end
 
 I would translate this to this PIR code:
 
 .sub _main
new_pad 0
 
# local p = 123
.local pmc p
p = new .PerlInt
p = 123
store_lex 0, p, p

If I recall, store_lex 0 is meaningless, and you ought to be using
either store_lex 1 or store_lex -1.  Not too sure about this one though.

 
# local q = 345
.local pmc q
q = new .PerlInt
q = 345
store_lex 0, q, q
 
newsub $P0, .Closure, _foo
 
# foo(q)
.arg q  
$P0()

Shouldn't this be:

$P0(q)

?  And likewise below?

 
# foo(q)
.arg q
$P0()
 
end
 .end
 
 .sub _foo
.param pmc a
   
# print(p);
find_lex $P0, p
print $P0
 
# p = p + p;
$P0 = $P0 + $P0

I feel a little uneasy about this line.  I'm not sure how PIR interprets
this.

store_lex p, $P0
 
# print(typeof(a));
$S0 = typeof a   
print $S0  # 
   
# print(a);
print a # ERROR!
 .end
 
 My problem with the last 2 statements is:
 - the statement print(typeof(a)); print SArray, which I don't understand.

I'm going to guess that that's due to your use of .arg above.

Luke


Re: Closures and subs

2004-11-04 Thread Klaas-Jan Stol


I now see I made some errors (I explain below)
First, I show the Lua code:
function newCounter ()
 local i = 0
 return function ()   -- anonymous function
   i = i + 1
   return i
 end
end
   c1 = newCounter()
print(c1())  -- 1
print(c1())  -- 2
This is the translation (and it works! :-)
.sub _newcounter
   new_pad 0
   # local i = 0
   .local pmc i
   i = new .PerlInt
   i = 0
   store_lex -1, i, i
   # create closure of function to return
   .local pmc clos
   newsub clos, .Closure, _function
   # why should I do this? (should I?) .return clos does not work 
(then it's whining about SArray again)
THIS should be done with a .pcc_begin/end_return pair, and with use of a 
.return statement:

   P5 = clos
.end
.sub _function
   # i = i + 1
   .local pmc j
   find_lex j, i
   j = j + 1
THIS print should not be here:
   print j
   store_lex -1, j, j
   # return i
THIS should be enclosed in .pcc_begin/end_return pair:
   .return j 

.end
.sub _main @MAIN
   # c1 = newcounter()
   .local pmc c1
   c1 = _newcounter()
 # print(c1())   Prints 1
   .local pmc i  i = c1()
   print i
   print \n
   # print(c1())   Prints 2
   i = c1()
   print i
   print \n
   # print(c1())   Prints 3
   i = c1()
   print i
   print \n
   end
.end
So, this one works. I guess my question concerns syntax: why doesn't 
.return clos in newclosure() work?

Klaas-Jan

WHoops, I see I made a mistake:
1. it didn't work, like I thought. There was some print statement which 
shouldn't be there, which caused me thinking it worked.
2. P5 = clos can be replaced by a .pcc_begin/end_return pair.

So, I think I 've got my answer there !
thanks anyway,
klaas-jan



Please, Help on I/O

2004-11-04 Thread Christian Aperghis-Tramoni
I have the folowing program :
print   Give me an integer number : ¥n
getstdinP0
readline S1,P0
Its execution gives :
10
Give me an integer number :
How is it possible to flush stdout before reading the number.
It means the equivalent of the $| in Perl.
__
   \|||/
   (o o)
 +--ooO-( )-Ooo--+
 |  Christian Aperghis-Tramoni   |
 |   |
 | Case Postale 901  Tel : (33) 04 91 82 92 49   |
 | 163 Avenue de Luminy  SFR : (33) 06 18 93 10 70   |
 | 13288 Marseille Cedex 09  Fax : (33) 04 91 82 92 75   |
 | FranceMel : [EMAIL PROTECTED] |
/) [EMAIL PROTECTED](\
   / ) WEB : http://www.dil.univ-mrs.fr/~chris   ( \
  ( (+---+) )
 ((\ \)  / )   / ) (/ //)
 (\\\ \_/ /\ \_/ ///)
  \ /\ /
___\___/__\___/
print join('',map({$i=1-$i;$a=$i?10*$_.\b\b:packc,$a+$_+0x16}split
(//,5110789279758710838810587992861093898779948387799310)),...\n);
___


Re: Please, Help on I/O

2004-11-04 Thread Marty Pauley
On Thu Nov  4 11:53:45 2004, Christian Aperghis-Tramoni wrote:
 
 It means the equivalent of the $| in Perl.

You can switch off buffering on stdout by doing:

getstdout P1
pioctl I0, P1, 3, 0

To switch back to line buffering, do:

getstdout P1
pioctl I0, P1, 3, 1

-- 
Marty


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Sam Ruby
Jeff Clites wrote:
On Nov 3, 2004, at 8:09 AM, Dan Sugalski wrote:
At 11:04 AM -0500 11/3/04, Sam Ruby wrote:

A single pow_p_p_p op backed by a (non-MMD) vtable entry would make 
it easier to support code like the following:

  def f(x): return x**3
  print f(3), f(2.5)

Yeah, it would. I know I'm going to regret asking, but... any reason 
*not* to make it MMD? (Though I have no idea what happens if you 
square a matrix)
I feel like we have op-itis and vtable-itis. I would think that rather 
than a pow_p_p_p, you'd compile x**y as something like:

set N0, P0
set N1, P1
pow N2, N0, N1
new P2, .PythonNumber
assign P2, N2
I.e., PMCs don't inherently exponentiate--numbers do, and you can 
exponentiate PMCs by numberizing them, exponentiating, and creating a 
PMC with the result.

Or, if we must have an op, implement it something like this (without 
needing a new vtable entry, or MMD):

inline op pow(out PMC, in PMC, in PMC) :base_core {
  $1 = pmc_new(interpreter, $2-vtable-type(interpreter, $2));
  $1-vtable-set_number_native(interpreter, $1,
 pow( $2-vtable-get_number(interpreter, $2),
 $3-vtable-get_number(interpreter, $3)))
  goto NEXT();
}
Those would probably JIT to about the same thing, given register mapping.
This is the viewpoint that pow() isn't a fundamental operation that 
makes sense for all types; it's a numeric operation, which can be 
extended in a straighforward manner to types which know how to represent 
themselves as numbers. (e.g., it's gibberish to raise a ManagedStruct to 
a ParrotIO power, except that you can stretch and interpret such a thing 
as just implicit num-ification of the arguments.)
From a Python or Ruby language perspective, infix operators are not 
fundamental operations associated with specific types, they are 
syntactic sugar for method calls.

A the moment, I'm compiling x=y**z into:
x = y.__pow__(z)
There is nothing reserved about the name __pow__.  Any class can 
define a method by this name, and such methods can accept arguments of 
any type, and return objects of any type.  They can be called 
explicitly, or via the infix syntax.

What's the downside of compiling this code in this way?  If you are a 
Python programmer and all the objects that you are dealing with were 
created by Python code, then not much.  However, if somebody wanted to 
create a language independent complex number implementation, then it 
wouldn't exactly be obvious to a Python programmer how one would raise 
such a complex number to a given power.  Either the authors of the 
complex PMC would have to research and mimic the signatures of all the 
popular languages, or they would have to provide a fallback method that 
is accessible to all and educate people to use it.

Ultimately, Parrot will need something akin to .Net's concept of a 
Common Language Specification which defines a set of rules for 
designing code to interoperate.  A description of .Net's CLS rules can 
be found in sections 7 and 11 (a total of six pages) in the CLI 
Partition I - Architecture document[1].

- Sam Ruby
[1] http://msdn.microsoft.com/net/ecma/


Re: [PATCH] dynclass build

2004-11-04 Thread Dan Sugalski
At 10:07 AM +0100 11/4/04, Leopold Toetsch wrote:
Sam Ruby [EMAIL PROTECTED] wrote:
 Attached patch makes building in the dynclass ghetto a bit less
 inhospitable...
Thanks, applied.
Are we comfortable adding the dynclasses to the default build target? 
I want to at some point, if only to make really sure that we don't 
break them. (As stuff that gets built and tested by default stays up 
to date, while the rest... tends not to)
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: [PATCH] dynclass build

2004-11-04 Thread Sam Ruby
Dan Sugalski wrote:
At 10:07 AM +0100 11/4/04, Leopold Toetsch wrote:
Sam Ruby [EMAIL PROTECTED] wrote:
 Attached patch makes building in the dynclass ghetto a bit less
 inhospitable...
Thanks, applied.
Are we comfortable adding the dynclasses to the default build target? I 
want to at some point, if only to make really sure that we don't break 
them. (As stuff that gets built and tested by default stays up to date, 
while the rest... tends not to)
The best way to find out is to add it.
I would prefer that this be added sooner rather than later, and now is 
as good a time as any.

Within a day or so, I should have an initial set of python PMCs that I 
would like to see committed, as well as the beginnings of a test suite.

- Sam Ruby


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Dan Sugalski
At 1:19 AM -0800 11/4/04, Jeff Clites wrote:
On Nov 3, 2004, at 8:09 AM, Dan Sugalski wrote:
At 11:04 AM -0500 11/3/04, Sam Ruby wrote:

A single pow_p_p_p op backed by a (non-MMD) vtable entry would 
make it easier to support code like the following:

  def f(x): return x**3
  print f(3), f(2.5)
Yeah, it would. I know I'm going to regret asking, but... any 
reason *not* to make it MMD? (Though I have no idea what happens if 
you square a matrix)
I feel like we have op-itis and vtable-itis. I would think that 
rather than a pow_p_p_p, you'd compile x**y as something like:
Or, in this case, MMD-itis, since that's the right thing to do here.
If it can be overridden, and in this case it certainly can, then we 
must allow for it. We only get to scam for speed *after* we meet the 
basic language requirements.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: Quality from the Beginning: Better Estimates

2004-11-04 Thread Mark Stosberg
Thanks for all the feedback and suggestions for improving estimation.
Based on this and other research, I expect to make a sort of best
practices documentation for use at my small professional services firm.
I'm thinking of including these key parts in it:

 1. A checklist of things to consider when estimating. This is especially for
the non programming parts. While not meant to be comprehensive, it
may help to jar the memory about factors that come into play. 

 2. Have all significant estimates peer reviewed. Perhaps
reality-checked is more what I have in mind. Did I leave out some
part of the process that takes time?  Does anything seem really off?

 3. A spreadsheet to document past estimates, with columns for
estimated time, actual time, scope, and risk factors 

 4. Reward good estimates. :) 


Comments?

Mark

-- 
 . . . . . . . . . . . . . . . . . . . . . . . . . . . 
   Mark StosbergPrincipal Developer  
   [EMAIL PROTECTED] Summersault, LLC 
   765-939-9301 ext 202 database driven websites
 . . . . . http://www.summersault.com/ . . . . . . . .



estimating other people's work (was Re: Quality from the Beginning: Better Estimates)

2004-11-04 Thread Mark Stosberg
I also have a follow-up question: 

Another real world constraint is that sometimes by the time the client
approves the quote, I'm involved in another project and it works better
logistically to have another programmer complete the task (or help with
it). 

Since programmers are not plug and play units, we have different
levels of efficiency.

What, if anything, do you to do address this in estimates? Perhaps you
feel there's generally programmer parity and don't worry so much about
this.

I, for one, know I can feel uneasy if I have to work on a budget for
programming work that I didn't contribute to myself.   

Mark

-- 
 . . . . . . . . . . . . . . . . . . . . . . . . . . . 
   Mark StosbergPrincipal Developer  
   [EMAIL PROTECTED] Summersault, LLC 
   765-939-9301 ext 202 database driven websites
 . . . . . http://www.summersault.com/ . . . . . . . .



Does Parrot have True coroutines?

2004-11-04 Thread Klaas-Jan Stol
Hello,
I spoke (through email) with Roberto Ierusalimschy, one of the creators of the Lua 
programming language, and I said that Parrot has good support for implementing 
coroutines and closures (heck, they are explicitly there).
However, in a reply, Roberto asked:
Are you sure Parrot support true coroutines? Does it integrate
coroutines and closures correctly? (For instance, a single closure may
refer to variables in several different coroutines.)
M, I wouldn't know.  In Lua, one can create a coroutine explicitly (through a kind of 
package coroutine, an example is included:
co = coroutine.create(function ()
  for i=1,10 do
print(co, i)
coroutine.yield()
  end
end)
Anybody got a clue on whether Parrot has true coroutines?
thanks,
Klaas-Jan 




Re: No Cpow op with PMC arguments?

2004-11-04 Thread Leopold Toetsch
Jeff Clites [EMAIL PROTECTED] wrote:

 I feel like we have op-itis and vtable-itis.

I'm for sure the last one that would add an opcode or a vtable, if it's
not needed. But in that case it has to be one. The PMC can be any kind
of plain scalar and also *complex*. We have different operations with
different results.

So your example

 set N0, P0
 set N1, P1
 pow N2, N0, N1

doesn't work for complex numbers.

$1-vtable-set_number_native(interpreter, $1,

Same problem.

 JEff

leo


Re: Closures and subs

2004-11-04 Thread Leopold Toetsch
Klaas-Jan Stol [EMAIL PROTECTED] wrote:

 Thanks for your quick reactions.

You are welcome.

 Indeed, doing

  $P0(q)

 works ok. I'm a bit confused by syntax then (but I think it makes sense
 now, if IMCC sees the (, it is expecting args I guess)

Yep. Function and method calls as well as *returns* have their arguments
in parenthesis.

 In the mean time, I wrote another example for closures (maybe I should
 collect these in a HOWTO document :-)

Yes please.

 (This one *is* working, however, again I don't understand why some
 things have to be done in a particular way)

 newsub clos, .Closure, _function
 # why should I do this? (should I?) .return clos does not work
 (then it's whining about SArray again)
 P5 = clos

  .return(clos)

 find_lex j, i
 j = j + 1
 print j
 store_lex -1, j, j

The store_lex isn't really necessary, as you are modifying j in place-

 .return j

  .return(j)

 Klaas-Jan

leo


Re: [PATCH] dynclass build

2004-11-04 Thread Dan Sugalski
At 3:51 PM +0100 11/4/04, Leopold Toetsch wrote:
Dan Sugalski [EMAIL PROTECTED] wrote:
 Are we comfortable adding the dynclasses to the default build target?
I think it can go in.
Lets do that then.
  I want to at some point, if only to make really sure that we don't
 break them. (As stuff that gets built and tested by default stays up
 to date, while the rest... tends not to)
Good point. We need tests:
1) basic operation: is dynclass loading working (current samples,
   modified not to use absolute type numbers)
2) Where should dynamic {tcl, perl, python, ...}_classes tests go?
   t/xt/$lang   # xt for extension and test sorting?
If the individual dynclasses have pir or pasm that can test them, 
then it can go in t/dynclass/pmcname.t. If it needs anything 
fancier... we can punt for now. Language specific PMCs can be tested 
in the language's test suite, I expect.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: [PATCH] dynclass build

2004-11-04 Thread Leopold Toetsch
Dan Sugalski [EMAIL PROTECTED] wrote:

 Are we comfortable adding the dynclasses to the default build target?

I think it can go in.

 I want to at some point, if only to make really sure that we don't
 break them. (As stuff that gets built and tested by default stays up
 to date, while the rest... tends not to)

Good point. We need tests:
1) basic operation: is dynclass loading working (current samples,
   modified not to use absolute type numbers)

2) Where should dynamic {tcl, perl, python, ...}_classes tests go?

   t/xt/$lang   # xt for extension and test sorting?

leo


Intermittently Failing Benchmarks

2004-11-04 Thread Joshua Gatcomb
All:
In collecting the historical data for the benchmark
statistics and graphs, I discovered that there were a
few days where I had to play the CVS time game to get
a working parrot for that day.  I expected this.

What I have found interesting though is when
individual benchmarks don't work.  For instance, from
10/20 to 10/22, gc_generations and gc_header_reuse
would just hange (still running after 10 minutes). 
Last night (11/3 at 23:59) addit2.imc is doing the
same thing.  I checked a up to the minute checkout and
it is finishing now - but there is no printed output.

So I have 2 questions:
1.  Would people prefer missing data for benchmarks
where they won't work or a manually entered high
number to draw attention to them?
2.  Should we be checking that the output of the
benchmarks (right or wrong) is consistent?

Cheers
Joshua Gatcomb
a.k.a. Limbic~Region



__ 
Do you Yahoo!? 
Check out the new Yahoo! Front Page. 
www.yahoo.com 
 



Re: estimating other people's work (was Re: Quality from the Beginning: Better Estimates)

2004-11-04 Thread Stevan Little
Mark,
This can be an issue, however I think it is easily solved.
1) Use a mean between the most efficient and least efficient 
programmers times, since it could be either one (and probably both) who 
work on it.

In many situations, your more efficient programmer is managing your 
less efficient programmers, so the more efficient one will have an idea 
of what that 'mean' time will be, and maybe even give that to you from 
the start knowing full well that he/she might not do all the work on 
it.

2) Keep good programmers around.
This is not as simple as is sounds, since we all know programmers (me 
included) are moody beasts. But I know for me, if I am challanged and 
feel respected, I will stick around. Its only when I am bored and don't 
feel like I am contributing and respected that I will start surfing the 
job boards during my lunch hour.

The basic idea is that you try to avoid having too much of a difference 
between the most efficient programmers and the least efficient, and 
therefore reduce this problem as a whole while also increasing the 
quality of your product (and you can see all the futher benefits I'm 
sure).

Hope this helps.
BTW - Interesting thread, it got me thinking more analytically about my 
own approach.

Steve
On Nov 4, 2004, at 10:18 AM, Mark Stosberg wrote:
I also have a follow-up question:
Another real world constraint is that sometimes by the time the client
approves the quote, I'm involved in another project and it works better
logistically to have another programmer complete the task (or help with
it).
Since programmers are not plug and play units, we have different
levels of efficiency.
What, if anything, do you to do address this in estimates? Perhaps you
feel there's generally programmer parity and don't worry so much 
about
this.

I, for one, know I can feel uneasy if I have to work on a budget for
programming work that I didn't contribute to myself.
Mark
--
 . . . . . . . . . . . . . . . . . . . . . . . . . . .
   Mark StosbergPrincipal Developer
   [EMAIL PROTECTED] Summersault, LLC
   765-939-9301 ext 202 database driven websites
 . . . . . http://www.summersault.com/ . . . . . . . .




Re: Intermittently Failing Benchmarks

2004-11-04 Thread Matt Diephouse
On Thu, 4 Nov 2004 08:57:28 -0800 (PST), Joshua Gatcomb
[EMAIL PROTECTED] wrote:
 What I have found interesting though is when
 individual benchmarks don't work.  For instance, from
 10/20 to 10/22, gc_generations and gc_header_reuse
 would just hange (still running after 10 minutes).
 Last night (11/3 at 23:59) addit2.imc is doing the
 same thing.  I checked a up to the minute checkout and
 it is finishing now - but there is no printed output.

Maybe the benchmarks should be part of the test suite? They're valid
code, so they should work at all times: if they don't, something's
broken. Seems like a good opportunity for testing to me.

-- 
matt


Re: Intermittently Failing Benchmarks

2004-11-04 Thread Leopold Toetsch
Matt Diephouse [EMAIL PROTECTED] wrote:

 Maybe the benchmarks should be part of the test suite? They're valid
 code, so they should work at all times: if they don't, something's
 broken. Seems like a good opportunity for testing to me.

Yep.

Patches welcome. But please make sure that they don't run too long.
Output of a few (gc_*.pasm comes to my mind) needs some tweaking WRT
result.

leo


Re: Does Parrot have True coroutines?

2004-11-04 Thread Leopold Toetsch
Klaas-Jan Stol [EMAIL PROTECTED] wrote:
 Hello,

 Are you sure Parrot support true coroutines? Does it integrate
 coroutines and closures correctly? (For instance, a single closure may
 refer to variables in several different coroutines.)

Well, I don't know how true coroutines are defined, but Parrot, as
it's CPS based, has no problems with coroutines and there are no
restrictions to coroutines, AFAIK.

How coroutines finally really behave WRT argument passing isn't really
layed out. There is a good article in Dan's blog IIRC.

 co = coroutine.create(function ()
for i=1,10 do
  print(co, i)
  coroutine.yield()
end
  end)

In Parrot's enough to include a .yield() ...

,--[ simplest usage ]-
| $ cat coro.imc
| .sub main @MAIN
|   $I0 = coro()
|   print $I0
|   $I0 = coro()
|   print $I0
| .end
| .sub coro
|   .yield(4)
|   .yield(2)
| .end
|
| $ ./parrot coro.imc
| 42
`-

to get a static coroutine. Above Lua snippet would use the Cnewsub
opcode to create a Coroutine function object. Such objects act as
closures too (modulo untested, unimplemented features ;)

 thanks,
 Klaas-Jan

leo


Branching off the tree

2004-11-04 Thread Dan Sugalski
Since I'm about to start in on some of the Irrevocable Changes (or 
something like that) to the string system with the new 
encoding/charset stuff, I tagged CVS and will be working in a branch 
(I hope).

If you feel like watching or playing along at home, the branch is 
pluggable_encodings, assuming I did this all right.
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: special blocks tests fail on 5.8.0

2004-11-04 Thread Paul Johnson
On Thu, Oct 28, 2004 at 01:31:40PM +1000, [EMAIL PROTECTED] wrote:

 I dont know if the code under test is wrong or the expected output.
 
 I run RH9, which uses Perl 5.8.0. I was getting a failure for 
 t/aspecial_blocks, indicating a difference in the expected output for a 
 CHECK {} block.

If I remember correctly, RH9 shipped with a 5.8.0 which was really 5.8.0
plus a bunch of patches.  I suspect that one of those patches is causing
this behaviour, enabling Devel::Cover to check the coverage of your
CHECK blocks.  You'll notice that your patch effectively brings
test_output/cover/special_blocks.5.008 up to
test_output/cover/special_blocks.5.008001.

 IF the expected output is wrong, I have provided a patch of the 
 test_output/cover/special_blocks.5.008 golden file.

So, I won't apply this patch, since it would break every standard 5.8.0
installation, but thanks very much for taking the trouble to create it.

And the good news is that you can safely use Devel::Cover, with the
added bonus of getting your CHECK blocks covered.

 I dont have a patch if the code under test is wrong, wouldnt even have a 
 clue where to start - I ran t/aspecial_blocks under Devel::ptkdb, and 
 realised I'd need to dig a lot deeper to find out where the code goes...
 
 Can anyone give me a hint to track the code for a CHECK block? Do I have 
 to trace the dynamically generated command maually ?

If you are still interested, the code in question is in Cover::report(),
the section that starts if (exists B::check_av).  In a standard 5.8.0
that would be false.  In 5.8.1 and, it would seem, RH9 5.8.0 it is true.

-- 
Paul Johnson - [EMAIL PROTECTED]
http://www.pjcj.net


Search paths and library routines

2004-11-04 Thread Dan Sugalski
Okay, this has been an ongoing source of annoyance, and I think it's 
time to address it.

We need to get search paths for loading of stuff into parrot, both at 
the pir/pasm assembly level and at runtime for dynamic library 
loading.

Now, bizarrely enough, I *don't* want to build this into parrot. 
(Yeah, I know. Yes, I am feeling OK :) At least not the runtime 
library loading, and if we can skip it for the assembly level that'd 
be fine too. What I'd like to do is pass off the job of finding 
generally-unqualified names to a library routine and have it look for 
the thing for me. That means we need a method of registering search 
paths (which ought be a library routine itself) too. So I'd like that 
stuff in the library.

To make this actually work we need some standards, and the ability to 
embed bytecode segments into an executable (like, say, parrot :) so 
they're always at hand. Hard to load in your library if your library 
finding code's in the library, after all. I'm also not averse to some 
sort of special accommodation for low-level library code so it can be 
found relatively quickly without a full namespace search if it seems 
necessary, though I'm not so sure about that one. We'll see.

Note here that I'm not talking about perl/python/ruby/tcl's standard 
library here -- this is parrot's low-level library, stuff that we 
need but isn't time-critical enough to warrant opcodes.

So. Anyone want to champion parrot's standard library? And anyone 
want to take a shot at getting fully functioning embeddable bytecode, 
along with spec'ing out whatever (hopefully minimal) APIs might be 
needed to make 'em work?
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Shared library question

2004-11-04 Thread Sam Ruby
Background: Pmc2c.pm emits code which references Parrot_PMC_typenum. 
This code is present in libparrot.so, which currently is not referenced 
as a library by the link step for dynclasses.

Options include:
  1) eliminating this dependency, as it is the only one
  2) directly including extend.o into each shared library
  3) linking to libparrot.so
As an added complication, the link step for dynclasses is by default run 
from a different directory than the main build.

Preferences?
- Sam Ruby


Re: Shared library question

2004-11-04 Thread Dan Sugalski
At 3:49 PM -0500 11/4/04, Sam Ruby wrote:
Background: Pmc2c.pm emits code which references Parrot_PMC_typenum. 
This code is present in libparrot.so, which currently is not 
referenced as a library by the link step for dynclasses.

Options include:
  1) eliminating this dependency, as it is the only one
  2) directly including extend.o into each shared library
  3) linking to libparrot.so
#3's the right thing here. PMC classes have access to enough of the 
internals that linking to libparrot's fine. If we're feeling paranoid 
we can define a PMC API and link against a shared library that 
exposes it, but that's a bit much for now.

As an added complication, the link step for dynclasses is by default 
run from a different directory than the main build.
Pfui. Probably ought to be fixed.
--
Dan
--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: Does Parrot have True coroutines?

2004-11-04 Thread Klaas-Jan Stol

Well, I don't know how true coroutines are defined, but Parrot, as
it's CPS based, has no problems with coroutines and there are no
restrictions to coroutines, AFAIK.
 

To be honest, I hadn't thought of this, either (this true-ness of 
coroutines), but then again, I'm no expert on these things.

How coroutines finally really behave WRT argument passing isn't really
layed out. There is a good article in Dan's blog IIRC.
 

I'll read it again.
 

co = coroutine.create(function ()
  for i=1,10 do
print(co, i)
coroutine.yield()
  end
end)
   

In Parrot's enough to include a .yield() ...
,--[ simplest usage ]-
| $ cat coro.imc
| .sub main @MAIN
|   $I0 = coro()
|   print $I0
|   $I0 = coro()
|   print $I0
| .end
| .sub coro
|   .yield(4)
|   .yield(2)
| .end
|
| $ ./parrot coro.imc
| 42
`-
 

I hadn't seen .yield(x)
Is
   .yield(x)
the same as:
   .pcc_begin_yield
   .return x
   .pcc_end_yield
?
to get a static coroutine. Above Lua snippet would use the Cnewsub
opcode to create a Coroutine function object. Such objects act as
closures too (modulo untested, unimplemented features ;)
 

So, correct me if I'm wrong, a Coroutine is also a closure?
In that case, anytime you would create a closure, you could also create 
a coroutine?

I've also included the reply I got from Roberto:
quote
Untested code:

function f(x)
 A = function () 
   x=x+1 
 end

 B = coroutine.wrap(
   function (y)
 C = coroutine.wrap(
   function (z)
 while true do 
coroutine.yield(x+y+z) 
 end
   end)
   
 while true do
   y=y+1
   coroutine.yield()
 end
   end)
end

X = f()
--
Now we have:
- function A: each call increments x (in the main thread)
- coroutine B: each call increments y (in that coroutine)
- coroutine C: each call returns x+y+z (each in a different coroutine)
Of course, all this wold be more fun with recursion  :) 
-- Roberto

/quote
Do you think the above code snippet could work? That is, without much 
special code, can this be done in PIR?
(Of course, why would one ever want to write /such/ code :-P, but that's 
another issue)

Thanks,
Klaas-Jan



Re: Are we done with big changes?

2004-11-04 Thread Matt Diephouse
On Tue, 2 Nov 2004 13:35:09 -0500, Dan Sugalski [EMAIL PROTECTED] wrote:
 What, think this warrants a 0.1.2 release? I'm not so sure about
 that. It's not that big a deal...

In the past week, Parrot has seen a dramatic speedup. We're in about
the best shape we've been in in the past 4 months:

 http://www.sidhe.org/~timeparrot/graphs/A/sum.png

Seems like a pretty big deal.

-- 
matt


Re: Are we done with big changes?

2004-11-04 Thread Dan Sugalski
At 4:38 PM -0500 11/4/04, Matt Diephouse wrote:
On Tue, 2 Nov 2004 13:35:09 -0500, Dan Sugalski [EMAIL PROTECTED] wrote:
 What, think this warrants a 0.1.2 release? I'm not so sure about
 that. It's not that big a deal...
In the past week, Parrot has seen a dramatic speedup. We're in about
the best shape we've been in in the past 4 months:
 http://www.sidhe.org/~timeparrot/graphs/A/sum.png
Seems like a pretty big deal.
Hrm. Okay, then, if I've not managed to make a mess of things with 
the stuff I've been doing, why don't we do a 0.1.2 performance 
release? Between the speedups and the gentler effects of -t it seems 
likely to be worth it for people who're working with parrot to do 
stuff. (Better -t definitely makes debugging a *lot* less painful...)
--
Dan

--it's like this---
Dan Sugalski  even samurai
[EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk


Re: Does Parrot have True coroutines?

2004-11-04 Thread Michael Walter
I sense confusion between closure, continuation and coroutine.

http://c2.com/cgi/wiki?ContinuationExplanation
http://c2.com/cgi/wiki?ContinuationsAndCoroutines
http://c2.com/cgi/wiki?CoRoutine
http://c2.com/cgi/wiki?LexicalClosure

Cheers,
Michael


On Thu, 04 Nov 2004 22:11:07 +0100, Klaas-Jan Stol [EMAIL PROTECTED] wrote:
 
 Well, I don't know how true coroutines are defined, but Parrot, as
 it's CPS based, has no problems with coroutines and there are no
 restrictions to coroutines, AFAIK.
 
 
 To be honest, I hadn't thought of this, either (this true-ness of
 coroutines), but then again, I'm no expert on these things.
 
 How coroutines finally really behave WRT argument passing isn't really
 layed out. There is a good article in Dan's blog IIRC.
 
 
 I'll read it again.
 
 
 
 
 
 co = coroutine.create(function ()
for i=1,10 do
  print(co, i)
  coroutine.yield()
end
  end)
 
 
 
 In Parrot's enough to include a .yield() ...
 
 ,--[ simplest usage ]-
 | $ cat coro.imc
 | .sub main @MAIN
 |   $I0 = coro()
 |   print $I0
 |   $I0 = coro()
 |   print $I0
 | .end
 | .sub coro
 |   .yield(4)
 |   .yield(2)
 | .end
 |
 | $ ./parrot coro.imc
 | 42
 `-
 
 
 
 I hadn't seen .yield(x)
 Is
 .yield(x)
 
 the same as:
 
 .pcc_begin_yield
 .return x
 .pcc_end_yield
 ?
 
 to get a static coroutine. Above Lua snippet would use the Cnewsub
 opcode to create a Coroutine function object. Such objects act as
 closures too (modulo untested, unimplemented features ;)
 
 
 
 So, correct me if I'm wrong, a Coroutine is also a closure?
 In that case, anytime you would create a closure, you could also create
 a coroutine?
 
 I've also included the reply I got from Roberto:
 quote
 
 Untested code:
 
 function f(x)
   A = function ()
 x=x+1
   end
 
   B = coroutine.wrap(
 function (y)
   C = coroutine.wrap(
 function (z)
   while true do
  coroutine.yield(x+y+z)
   end
 end)
 
   while true do
 y=y+1
 coroutine.yield()
   end
 end)
 end
 
 X = f()
 --
 Now we have:
 
 - function A: each call increments x (in the main thread)
 
 - coroutine B: each call increments y (in that coroutine)
 
 - coroutine C: each call returns x+y+z (each in a different coroutine)
 
 Of course, all this wold be more fun with recursion  :)
 -- Roberto
 
 /quote
 
 Do you think the above code snippet could work? That is, without much
 special code, can this be done in PIR?
 (Of course, why would one ever want to write /such/ code :-P, but that's
 another issue)
 
 Thanks,
 Klaas-Jan
 



Re: Closures and subs

2004-11-04 Thread Piers Cawley
Leopold Toetsch [EMAIL PROTECTED] writes:

 Klaas-Jan Stol [EMAIL PROTECTED] wrote:
 Hello,

 I've been playing with closures and subs but I have a little bit of
 trouble with those.

  newsub $P0, .Closure, _foo
  $P0(q)
  newsub $P0, .Closure, _foo
  $P0(q)

 Closures have to be distinct.

Does this *really* mean that, if I create a closure in a function and
return it to my caller, that closure can only be invoked once?

If it does, this is slightly more broken than a very broken thing.


Re: Does Parrot have True coroutines?

2004-11-04 Thread Stéphane Payrard
On Thu, Nov 04, 2004 at 10:11:07PM +0100, Klaas-Jan Stol wrote:
 
 I hadn't seen .yield(x)
 Is
.yield(x)
 
 the same as:
 
.pcc_begin_yield
.return x
.pcc_end_yield
 ?
 

Yes. This alternative syntax has been checked in yesterday
and is documented in the updated calling_conventions.pod.
The parentheses are mandatory.
Similarly you have:

   .return(x)

which is equivalent to:

.pcc_begin_return
.return x
.pcc_end_return


--
 stef


Re: Search paths and library routines

2004-11-04 Thread Brent 'Dax' Royal-Gordon
Dan Sugalski [EMAIL PROTECTED] wrote:
 To make this actually work we need some standards, and the ability to
 embed bytecode segments into an executable (like, say, parrot :) so
 they're always at hand.

The attached patch implements one (evil) way to do this.  (Even if we
don't end up using the pbc2cc utility I've written, the patches to
embed.[ch] might be useful; they implement a new embedding interface
function for loading a packfile that's already in memory.)

-- 
Brent 'Dax' Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker

There is no cabal.
--- /dev/null   Wed Jan  7 17:19:56 2004
+++ pbc2cc.pl   Thu Nov  4 19:09:45 2004
@@ -0,0 +1,86 @@
+#!/usr/bin/perl -w
+
+=head1 TITLE
+
+pbc2cc.pl - Convert a Parrot bytecode file to a C constant
+
+=head1 SYNOPSIS
+
+pbc2cc.pl foo foo.pbc  foo.c
+#Generates a foo.c with a Parrot_pbc2cc_read_foo function
+# containing foo.pbc's contents.
+
+=head1 DESCRIPTION
+
+Fpbc2cc.pl converts an input file into a C constant, then outputs some code 
+to load that file as a Parrot packfile.  The program takes a C identifier and
+an input file on the command line (the input file defaults to STDIN if not 
+specified) and writes its output to STDOUT.  It also takes a C identifier to 
+be used as part of the function name to retrieve the packfile.
+
+The function generated has the signature:
+
+Parrot_PackFile Parrot_pbc2cc_read_name(Parrot_Interp interpreter);
+
+Where name is the C identifier given on the command line.
+
+=cut
+
+use strict;
+use File::Temp qw(tempfile);
+
+my($name, $in)[EMAIL PROTECTED];
+$in ||= '-';
+my $size=0;
+
+open(IN,  $in) or die Can't open input file $in: $!;
+my $temp=tempfile() or die Can't create temporary file: $!;
+
+binmode(IN);
+binmode($temp);
+
+{
+local $/=\1024;
+while(IN) {
+$size += length;
+print $temp $_;
+}
+}
+
+seek $temp, 0, 0;
+
+print END;
+/* 
+ * DO NOT EDIT THIS FILE
+ * This file has been automatically generated by $0 in the Parrot distribution.
+ */
+#ifndef PARROT_PBC2CC_${name}_GUARD
+#define PARROT_PBC2CC_${name}_GUARD
+
+#include stdlib.h
+#include string.h
+#include parrot/embed.h
+
+static const Parrot_Int Parrot_pbc2cc_size_$name=$size;
+/* gcc gives a warning about variable-size objects if we try to use that constant 
here */
+static const unsigned char Parrot_pbc2cc_bits_${name}[$size]={
+END
+
+{
+local $/=\16;
+while($temp) {
+print \t0x, join(, 0x, map { sprintf %2.2x, $_ } unpack C*, $_), 
,\n;
+}
+}
+
+print END;
+};
+
+Parrot_PackFile Parrot_pbc2cc_read_$name(Parrot_Interp interpreter) {
+\tunsigned char * rawfile=malloc(Parrot_pbc2cc_size_$name);
+\tmemcpy(rawfile, Parrot_pbc2cc_bits_$name, Parrot_pbc2cc_size_$name);
+\treturn Parrot_readbc_ptr(interpreter, $name (embedded), rawfile, 
Parrot_pbc2cc_size_$name, 0);
+}
+
+#endif
+END
Index: include/parrot/embed.h
===
RCS file: /cvs/public/parrot/include/parrot/embed.h,v
retrieving revision 1.25
diff -u -r1.25 embed.h
--- include/parrot/embed.h  2 May 2004 10:47:51 -   1.25
+++ include/parrot/embed.h  5 Nov 2004 03:25:33 -
@@ -36,6 +36,8 @@
 
 Parrot_PackFile Parrot_readbc(Parrot_Interp, const char *);
 
+Parrot_PackFile Parrot_readbc_ptr(Parrot_Interp, const char *, unsigned char *, 
size_t, Parrot_Int);
+
 void Parrot_loadbc(Parrot_Interp, Parrot_PackFile);
 
 void Parrot_setup_argv(Parrot_Interp, int argc, char ** argv);
Index: src/embed.c
===
RCS file: /cvs/public/parrot/src/embed.c,v
retrieving revision 1.119
diff -u -r1.119 embed.c
--- src/embed.c 22 Oct 2004 13:29:36 -  1.119
+++ src/embed.c 5 Nov 2004 03:25:33 -
@@ -201,7 +201,7 @@
 Parrot_readbc(Interp *interpreter, const char *filename)
 {
 INTVAL program_size, wanted;
-char *program_code;
+unsigned char *program_code;
 struct PackFile *pf;
 FILE * io = NULL;
 INTVAL is_mapped = 0;
@@ -325,14 +325,7 @@
 
 /* Now that we have the bytecode, let's unpack it. */
 
-pf = PackFile_new(is_mapped);
-
-if (!PackFile_unpack
-(interpreter, pf, (opcode_t *)program_code, program_size)) {
-PIO_eprintf(interpreter, Parrot VM: Can't unpack packfile %s.\n,
-filename);
-return NULL;
-}
+pf = Parrot_readbc_ptr(interpreter, filename, program_code, program_size, 
is_mapped);
 
 #ifdef PARROT_HAS_HEADER_SYSMMAN
 
@@ -347,6 +340,20 @@
 return pf;
 }
 
+struct PackFile *
+Parrot_readbc_ptr(Interp *interpreter, const char *name, unsigned char *ptr, size_t 
size, Intval is_mapped) {
+struct PackFile *pf = PackFile_new(is_mapped);
+
+if (!PackFile_unpack
+(interpreter, pf, (opcode_t *)ptr, size)) {
+PIO_eprintf(interpreter, Parrot VM: Can't unpack packfile %s.\n,
+name);
+return NULL;
+}
+
+return pf;
+}
+
 /*
 
 =item Cvoid


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Brent 'Dax' Royal-Gordon
Jeff Clites [EMAIL PROTECTED] wrote:
 I.e., PMCs don't inherently exponentiate--numbers do, and you can
 exponentiate PMCs by numberizing them, exponentiating, and creating a
 PMC with the result.

This is true.  But how do you define a number?  Do you include
floating-point?  Fixed-point?  Bignum?  Bigrat?  Complex?  Surreal? 
Matrix?  N registers don't even begin to encompass all the numbers
out there.

-- 
Brent 'Dax' Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker

There is no cabal.


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Jeff Clites
On Nov 4, 2004, at 8:29 PM, Brent 'Dax' Royal-Gordon wrote:
Jeff Clites [EMAIL PROTECTED] wrote:
I.e., PMCs don't inherently exponentiate--numbers do, and you can
exponentiate PMCs by numberizing them, exponentiating, and creating a
PMC with the result.
This is true.  But how do you define a number?  Do you include
floating-point?  Fixed-point?  Bignum?  Bigrat?  Complex?  Surreal?
Matrix?  N registers don't even begin to encompass all the numbers
out there.
Floating point, and possibly integer. Those are the numeric primitives 
of processors. Other aggregate mathematical types are always defined in 
terms of those (in a computing context), one way or another.

JEff


Re: No Cpow op with PMC arguments?

2004-11-04 Thread Brent 'Dax' Royal-Gordon
On Thu, 4 Nov 2004 21:46:19 -0800, Jeff Clites [EMAIL PROTECTED] wrote:
 On Nov 4, 2004, at 8:29 PM, Brent 'Dax' Royal-Gordon wrote:
  This is true.  But how do you define a number?  Do you include
  floating-point?  Fixed-point?  Bignum?  Bigrat?  Complex?  Surreal?
  Matrix?  N registers don't even begin to encompass all the numbers
  out there.
 
 Floating point, and possibly integer. Those are the numeric primitives
 of processors. Other aggregate mathematical types are always defined in
 terms of those (in a computing context), one way or another.

Yes, but your decomposition (N2=P2; N3=P3; N1=N2+N3; P1=N1) doesn't
take anything but the primitives into account.  It would destroy the
meaningfulness of performing a pow() on a complex number, or even just
a bignum (which the language isn't necessarily even aware will be
involved in a particular operation--many will convert smoothly between
integer and bignum).

Dynamic languages generally try to hide the reality of the machines
they run on from the programmer; things like pow only works on
numeric primitives smack the programmer in the face with that
reality.  (Sure, languages can work around it, but their various hacks
will probably be mutually incompatible and less efficient than just
doing it ourselves.)  Operations that only work with primitives makes
sense for hardware, but out here in the realm of software we can do
better.

-- 
Brent 'Dax' Royal-Gordon [EMAIL PROTECTED]
Perl and Parrot hacker

There is no cabal.