Re: pdd03 (calling conventions) revised; get_params vs. READONLY

2005-11-30 Thread Jonathan Sillito
On 11/29/05, Chip Salzenberg [EMAIL PROTECTED] wrote:
 I've reviewed pdd03 and brought it back from pdds/clip.

Thanks for reviving this document Chip. Way back when I implemented
some of the original lexical and calling code (like the scratchpad --
may it rest in peace). What is the status of the todo's mentioned in
the BUGS section, who is working on these -- I am looking for a place
to jump in. Also what is the status of the exception subsystem you
mentioned?

I guess one more todo I could take on is the add the use of the set_*
and get_* ops to examples/subs. A short example in the pdd might be
helpful too.

Jonathan


pdd20 questions

2005-11-30 Thread Jonathan Sillito
I have some clarification questions about the new pdd20 on lexical
variables -- likely stemming from my having been out of it for so
long. Also I am happy to send a patch to pdd20 capturing these
clarifications once I am sure I understand things correctly.

1. What is expected to be in P0 in:

   .lex $a, P0

2. Should we provide a way for a compiler to provide depths to the
find_lex and store_lex ops if it chooses to?

3. 'Call frame' is mentioned often--what is a call frame in the
context of continuation passing style?

4. In the section Closure creation: Capturing the lexical
environment, LexPad is used a couple of times when LexEnv is meant,
right?

5. Thinking about closure support vs. outer support - the difference
and the need for both mechanisms is not clear to me.

6. The pdd mentions walking the call stack to find frames ... but is
there a call stack? And finding lexpads on the call stack makes me
think of dynamic variable binding rather than lexical?

7. Finally, what is the status of the implementation?

(As an aside is there interest in having the names of the invoke ops
more consistent, say: callcc and callcc_method; or invokecc and
invokecc_method?)

Jonathan


Re: pdd20 questions

2005-11-30 Thread Jonathan Sillito
On 11/30/05, Chip Salzenberg [EMAIL PROTECTED] wrote:
 On Wed, Nov 30, 2005 at 12:02:08PM -0800, Jonathan Sillito wrote:
  I have some clarification questions about the new pdd20

  1. What is expected to be in P0 in:
 .lex $a, P0

 The .lex directive is compile-time only, and has no runtime effect
 on the contents of P0.  (Of course, once a register is available with
 a lexical name, store_lex may modify it.)

OK, so this directive makes $a an alias for P0.

  2. Should we provide a way for a compiler to provide depths to the
  find_lex and store_lex ops if it chooses to?

 Maximum depths, you mean?  I know of no use case for it.

Not maximum depth but the exact depth for a given lexical variable in
the case of closures. The reason would simply be performance, though
maybe insignificant in the common case (i.e. shallow nesting).

  5. Thinking about closure support vs. outer support - the difference
  and the need for both mechanisms is not clear to me.

 Could you unpack this, please?

Well, using :outer allows the look up algorithm to walk through
enclosing lexical scopes ($sub = $sub.outer). In the case of closures
the LexEnv is populated with the enclosing LexPads which I assume come
from enclosing lexical scopes, which allows the the look up to do the
same thing, no? I must be missing something here.

 Chip Salzenberg [EMAIL PROTECTED]

Thanks,
Jonathan


Re: pdd20 questions

2005-11-30 Thread Jonathan Sillito
On 11/30/05, Chip Salzenberg [EMAIL PROTECTED] wrote:

 What you're missing is that without the :outer information, Parrot
 wouldn't be able to decide *which* LexPads *should* be searched,
 either now (find_lex w/o LexEnv) or later (newclosure - LexEnv).

Right and I see that this is consistent with the closure creation
section (which is more clear now).

Thanks,
Jonathan


RE: [perl #22745] [PATCH] Parrot subroutines

2003-06-20 Thread Jonathan Sillito
The patch looks pretty good to me. Here is a proposal for an alternative
inheritance hierarchy. Invocable, the root of the hierarchy, is basically a
sub that is not a closure (i.e. *no* context at all, just an address).

pmclass Invocable { # I called this sublite before
  /* SELF-data is always NULL */
  /* SELF-cache.int_val holds address */

  void set_integer_native(INTVAL value) {
SELF-cache.int_val = value;
  }
  void* invoke() {
return (void*)SELF-cache.int_value;
  }

  ...
}

pmclass Sub extends Invocable {
  /* SELF-data is a lex_pad (or stack as Leo suggests) */
}

pmclass Continuation extends Invocable {
  /* SELF-data is a pointer to a Parrot_Context struct */
}

pmclass Coroutine extends Continuation {...} /* maybe ??? */

In the current implementation there is a difference between the sub pmc and
the struct Parrot_Sub. The same goes for continuations and coroutines. The
above suggests that we could merge those together and just have the pmc
versions.

--
Jonathan Sillito



RE: ad #22717: CPS and more

2003-06-19 Thread Jonathan Sillito
 -Original Message-
 From: Melvin Smith [mailto:[EMAIL PROTECTED]

 I tried this, and there was a distinct slowdown on accessing the regs
 through the dereference. Dan and I debated this because I had the same
 idea, but after profiling I proved Dan right. I think it is best
 optimized to
 the common case which is register access, not context switches.

However now the registers are no longer in the Parrot_Context struct, so it
may be worth revisiting this ...

 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

[snip]

 So all these subroutine types should have probably this structure:

 typedef struct Parrot_Sub {
  struct Parrot_Context ctx;
  opcode_t *address;
 } * parrot_sub_t;

Or a PMC with SELF-data pointing to a Parrot_Context struct and
SELF-cache.int_val holding the address?

 On *construction* they would do:

 all:  save_context(); // like in new_continuation
 sub, coro:push_current_lexpad_on_own_ctx();  // like new_coroutine

[snip]

Here is what I think. All of these things need an address and some amount of
context which is saved on construction and restored on invoke. The different
types the context to be saved and restored[1]:

  sublite[2]:
none - just address

  sub:
pointer to a lex pad

  coroutine:
whole Parrot_Context[3] - i.e same as ...

  continuation for cps approach:
whole Parrot_Context[3]

Sound correct?

--
Jonathan Sillito

[1] This is not considering other context information that Dan has been
talking about.
[2] This does not exist but could if we wanted to support subs that are not
closures - many are not.
[3] This is in the worst case, and I would like to see variations that are
more optimized.



RE: ad #22717: CPS and more

2003-06-18 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

 The patch is fine with two exceptions:
 1) still breaks existing P6C tests WRT exceptions  rules
 2) performance of CPS sucks

 ad 1) I'd like to preserve the old style invoke/ret scheme too. incokecc
 and friends could call a new ContSub[1] class, which is the same as
 sub.pmc but doesn't put the return address on the control stack during
 invoke.

 ad 2) CPS subroutines are 3 times slower for calling the sub. There are
 2 problems here:

 2a) The main is: the continuation object is generated for each[2]
 subroutine call. Replacing the invokecc with an explicit sequence of
 constructing the return Continuation object once outside the loop brings
 again the same speed as invoke/ret.

This is the reason for the new implementation of the invoke op which assumes
that the continuation has already been put in place. Also allowing the
invokecc to take an argument specifying the type of continuation to save may
be helpful:

invokecc .AddressOnlyContinuation # or something ...
invokecc .EverythingButTheKitchenSinkContinuation

 2b) There is still too much context copying going on AFAIK. The register
 top and base pointers are copied too in {save,restore}context worth of 8
 words, while just copying the 3 stacks (pad, control, user) should more
 then be enough. The coroutine code only swaps these - BTW and doesn't
 set them COW.

I am not sure I follow this. Are you suggesting that the register stacks do
not need to be copied? Again different types of continuations would be good.

 So we have currently:

 sub.pmc (+ contsub.pmc), continuation.pmc, and coroutine.pmc do very
 similar things. The only major difference is, where they branch on invoke.
 The differences are:
 - sub.pmc doesn't have an own context, it pushes the current lex_pad on
 the interpreters pad_stack on invoke
 - continuation.pmc saves/restores the whole context structure and marks
 the 3 stacks COW
 - coroutine.pmc swaps the 3 stacks and doesn't mark them COW

 This leads to some questions:
 - shouldn't these all preserve the same stack(s)?
 - which stack(s): pad_stack only or control/user/intstack too?
 - can we pull out the construction of the return continuation of the
 loop like done below?
 - what parts of current context structure should then be preserved
 (registers are already out, why then deal with register backing store)?

 Comments welcome

As suggested in a previous email coroutine.pmc could just go away. Since
returning from an otherwise normal sub using:

  invokecc P1

will save the appropriate context for a subsequent 'coroutine' call.

 leo


 [1] we could AFAIK reuse CSub, which is obsoleted by NCI.
   (also most routines in method_utils.c seems to be obsolete)

 [2]
   new P10, .PerlUndef
   set P10, 100
   new P11, .PerlUndef
   set P11, 0
   new P0, .Sub
   set_addr I12, func
   set P0, I12
   set I0, 0   # no prototype
   set I2, 0   # no PMC params
   set I3, 0   # void context
   new P1, .Continuation   ##
   set_addr I12, ret   ##
   set P1, I12 ##
 lp:
   pushbottomp
   invoke  ## invokecc
 ret:
   popbottomp
   inc P11
   lt P11, P10, lp
   end

 func:
   invoke P1





RE: ad #22717: CPS and more

2003-06-18 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

 Jonathan Sillito wrote:

 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]
 
 The patch is fine with two exceptions:
 1) still breaks existing P6C tests WRT exceptions  rules


 You didn't mention this point. It might be only a small change in P6C
 code, I didn't look at (4 tests are failing now due to invoke changes).

Sorry I haven't looked at this yet.

 2) performance of CPS sucks

  This is the reason for the new implementation of the invoke op
 which assumes
  that the continuation has already been put in place.


 Ok then we need a new opcode:

newsub Px, .Class, jump_or_ret_addr

Sounds fine to me. At one point the following worked:

new Px, .Class, address

 This constructs a sub or continuation type subroutine PMC in Px of class
 .Class and the referenced label  - in one instruction.

  Also allowing the
  invokecc to take an argument specifying the type of
 continuation to save may
  be helpful:


 No, don't think so. The type is specified by the PMC class. The invoke
 of this class takes the appropriate action.

I agree that constructing the continuation separately is functionally
equivalent:

new P1 .SomeContinuationClass, label# or newsub
invoke
label:
# return's to here

however I think a common case is made more convenient using:

invokecc .SomeContinuationClass  # assumes expr NEXT()
# return's to here

though, either way is fine with me.

 2b) There is still too much context copying going on AFAIK. The register
 top and base pointers are copied too in {save,restore}context worth of 8
 words, while just copying the 3 stacks (pad, control, user) should more
 then be enough. The coroutine code only swaps these - BTW and doesn't
 set them COW.

  I am not sure I follow this. Are you suggesting that the
 register stacks do
  not need to be copied? Again different types of continuations
 would be good.


 I honestly don't know, what has to be copied. I just know that all now
 do copy different things and if CPS is involved also restore different
 things. Please look at sub/continuation/coroutine and their context
 saving: all are different.

I guess this needs some reworking see below.

[snip]

 Still a lot (almost all) of my original concerns are not addressed yet.

And performance and consistency are the main concerns, correct? Following
are some ideas that may address theses.

(1) A continuation is an invokable pmc that contains some context and an
address to jump to. The context can vary and I suggest that we provide
several continuation types to support this. I think the following may make
sense (ordered from fastest to slowest).

  - no context (just an address)
  - just the pad stack
  - three stacks (pad, control and user)
  - three stacks plus register stacks

I suppose other variations could be added as well. I am not sure what names
to give each of these, but probably the no context pmc could be the base
extended by the others.

(2) Could the Parrot_Context struct be reworked such that the register
stacks are only one pointer each? This would make the save and restore
slightly more efficient.

(3) One other efficiency thought: I wonder if the interpreter's context
could be changed to a pointer to struct Parrot_Context? This would make
accessing the stacks slightly slower but would of course make restoring the
context very quick. Just a thought ...

What do you think?
--
Jonathan Sillito



RE: Context, continuations, and call speed

2003-06-13 Thread Jonathan Sillito
I missed this discussion I see, but for what it's worth, the patch I
submitted earlier in the week introduced a continuation pmc that does
**not** save or restore the registers. The old continuation pmc that saved
(including the registers) everything has been renamed to
completecontext.pmc.

On the other hand I like the idea several types of continuations including
one that saves and restores half of the registers.

Finally if the registers are never to be saved as part of the context, we
should reorganize the relevant structs so that the registers are not part of
the Parrot_Context struct.

Jonathan Sillito

 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]
 Sent: June 12, 2003 4:11 PM
 To: Luke Palmer
 Cc: [EMAIL PROTECTED]
 Subject: Re: Context, continuations, and call speed


 At 5:01 PM -0600 6/12/03, Luke Palmer wrote:
At 4:28 PM -0600 6/12/03, Luke Palmer wrote:
  Okay, at the moment I'm working on getting an implementation of
 classes and objects working. I'm also taking a look at
 calling speed,
 as I'd really like to not suck with our call times. :)
   
 First off, the core stuff looks good. I'd not really looked at it
 until now, but now that I have, well... good job folks. I put in a
 minor tweak that may or may not speed things up
 (basically checking
 for the COW flag on stack chunks and bailing on the walk up if
 they're already marked) depending on what's resident in the L1/L2
 cache. We'll see.
   
 Second, I see that the registers themselves are in the context
 structure. I think this may be a good part of our speed
 problem with
 taking continuations. Now, continuations should *not* restore the
 registers, so this strikes me as an incorrect thing to
 do, but before
 I twiddle the context structure some and remove them, I
 want to check
 and make sure that there's not a good reason to have them in.
   
   Well, aren't the registers really part of the context?
 
   Nope. If they were, there would be no way to return data from a
   function. The return values go in the registers, remember, and we
   return to the caller by invoking the continuation it passed into us.
 
 But they really are, honest.

 No. No, they aren't. Registers are really data, so arguably a
 continuation restore shouldn't restore *any* of the register stacks.
 That'd make things rather... odd, so we're not doing that. I may
 regret it in the future, of course.

 Continuations are supposed to save only control information, not
 data. Registers are data. (And so far as I know, no system that does
 continuations saves register contents for restore, since there'd be
 no way to pass data back and forth)

 Are the register stacks saved with the continuation?

 Yes, of course they are.
 --
  Dan

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




RE: Context, continuations, and call speed

2003-06-13 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

[snip]


 The compiler can't decide on not to emit saveall/restoreall - we are
 talking here about Parrot calling conventions and the caller saves all.

 The compiler may omit the saveall/restoreall on the last function call,
 *if* the compiler is really sure, that its calling really a leaf (If
 that returns with Cinvoke the compiler *doesn't* be sure).


The calling convention says that the caller saves everything that the caller
cares about, but that may not be everything. If a sub uses only one or two
registers it only needs to save those before calling another sub ... right?

--
Jonathan Sillito



RE: [perl #22633] [PATCH] convert parrot to continuation passing style

2003-06-11 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

 Jonathan Sillito [EMAIL PROTECTED] wrote:

  This patch converts parrot to a continuation passing style.

 You seem to be changing current tests WRT invoke - does invoke still
 work as it did? Or more specifically: Do imcc tests and perl6 test still
 pass?

Not quite. In the case of sub.pmc the 'next' argument to the invoke vtable
function is ignored, instead the continuation to return to is expected to be
in P1. All of what used to be just plain 'invoke' now should be
'invokecc' -- this will do the extra setup. So in the normal cases we should
use:

invokecc # rather than invoke
invoke P1# rather than ret

All imcc tests pass if the attached tiny patch is applied. Perl6 on the
other hand I have never looked at, but I can do that next I guess ...

Oh, one other difference is that 'invoke Px' will now put the sub from Px
into P0, since this is where the callee will expect it to be. Or is this
form of the op intended for something else?

  I am not satisfied with the time taken to make a call. I did some rough
  benchmarking and the parrot implementation makes us slower than python
  2.2.1.

 Optimized parrot build?

  $ perl assemble.pl test.pasm test.pbc ; time ./parrot  test.pbc

 CGP or jit should be a lot faster.

Adding --jit does not seem to make a difference. Am I missing somthing?

 Some minor remarks:
 - the changes s/interp/interpreter/ make it harder the read the real
   changes - and I don't see any benefit to rename variable names.

This was for consistency since everywhere else 'interpreter' seems to be
used.

 - you are undoing some PMC_data changes.

Doh!

--
Jonathan Sillito


imcc.patch
Description: Binary data


Re: [perl #22633] [PATCH] convert parrot to continuation passing style

2003-06-11 Thread Jonathan Sillito
On Wed, 11 Jun 2003, Leopold Toetsch wrote:

 Jonathan Sillito wrote:
 
 Why not just leave the old behaviour?
 IMHO[1]:
 - Make a new class based on Continuations
 - invokecc and such are based on it

[snip]

 [1] I don't know too much about all the HL stuff. But anyway, some 
 languages might be quite fine with the current implementation (which 
 seems to be more lightweight, when it just comes to calling a plain 
 subroutine) Have a look at P6Cs usage for exceptions and in regexen 
 code. I know, its not final, but its a working implementation. Some less 
 fancy HL might be just fine with the way how its working currently.
 
 Or I'm totally wrong here ;-)

Here is another suggestion (I think I mentioned this in another email) we 
could support a few different types of continuations. The simplest 
continuation could be just a saved return address (i.e. an opcode_t*). 
This would be roughly as lightweight as the current implementation, I 
think. What do you think? I am thinking it would be easier to have one 
calling convention then callees know what to expect.

  invokecc .LiteContinuation # or something ...

One more thing Leo (excuse my ignorance) why is there a stack calling 
convention in imcc? How does it relate to calling subs via the calling 
convention?

--
Jonathan Sillito



RE: [perl #22633] [PATCH] convert parrot to continuation passing style

2003-06-10 Thread Jonathan Sillito
 -Original Message-
 From: Jerome Vouillon [mailto:[EMAIL PROTECTED]

 The python interpreter seems rather slow.  I get these numbers with the
 Ocaml bytecode interpreter.

 mistral-jerome:/tmp  time python test.py
 python test.py  2,59s user 0,00s system 100% cpu 2,582 total
 mistral-jerome:/tmp  ocamlc -o tst test.ml; time ./tst
 ./tst  0,14s user 0,00s system 106% cpu 0,131 total
 mistral-jerome:/tmp  cat test.ml
 let foo () = () in
 for i = 1 to 100 do foo () done

That is impressive. I don't know Ocaml but do you think there is an
optimization being done since foo takes no args, returns not values and has
an empty body?

Also I should have mentioned that python spends between one third and one
half of its time executing the loop instructions (test and increment).
Parrot is much faster at this of course.

Parrot sub and method calls can be made faster or slower depending on how
much of the context needs to be saved. I can imagine several types of
continuations that differ on how much context they save and restore:

 a. only an opcode ptr to jump to
 b. opcode and the stacks
 c. opcode, stacks and half of the registers
 d. opcode, stacks and all of the registers

The patch I sent supports two types: type b (in continuation.pmc) and type d
(in completecontext.pmc). Also in this patch is the option to not create a
new continuation --as in a tail call-- which of course makes it very fast.

--
Jonathan Sillito



RE: [perl #22549] [PATCH] rename invoke to call, and more

2003-06-05 Thread Jonathan Sillito
Hey, thanks for the comments.

So you suggest leaving as the op as invoke? I don't mind, I just think we
should be consistent in our naming; what about having the following four
ops:

  - invoke
  - invokecc
  - invoke_method
  - invokecc_method

You also wondered about the need for the 'cc' variants of these ops. If
parrot's calling convention is to be continuation passing style then before
each invoke we need to set up a continuation (in P1). In the common case
this is just the current continuation. In pasm this could be:

new P1, .Continuation
set_addr I3, returnhere
set P1, I3

invoke   # or invoke_method
  returnhere:
# etc ...

With a 'cc' variant the common case is simplified to be just:

invokecc   # or invokecc_method
# etc ...

What do you think? Is it worth two more ops?

BTW does anyone (leo?, dan?) want to comment on my idea for getting rid of
the register stacks etc:

  calling convention and continuation ramblings
  http://xrl.us/iy8

Jonathan Sillito

 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

 Jonathan Sillito [EMAIL PROTECTED] wrote:

  1. some adding and renaming in core.ops, which gives the following ops:
 - call()
 - call(in PMC)

 Suboptimal. We will get a name clash in imcc. (Imcc has call as an alias
 for bsr)


  2. adds pmc access macros to register.h (as suggested by Mitchell).

 Thats fine.

  3. updates tests, examples and documentation to use call
 instead of invoke.
  still to do:
 - update language/imcc to use call instead of invoke??

 This - if ever - can only be done in one big change in parrot and imcc.

 But I don't know, why we actually should s/invoke/call/.  bsr/call is
 similar to a hardware CPU subroutine call, so I think, it should remain
 call (in imcc). invoke is a higher level construct and therfore deserves
 its special name.

 - add callcc and callcc_method - patch coming soon

 Why do we need another 2 ops? invoke on the appropriate class should be
 enough.

 leo




calling convention and continuation ramblings

2003-06-03 Thread Jonathan Sillito
I have a working implementation that that switches parrot to a continuation
passing style. While working on cleaning up a few things up, I got the
following idea ...

The current parrot context struct has a set of register stacks

struct IRegChunk *int_reg_top;
struct NRegChunk *num_reg_top;
etc ...

These are used when saving and restoring the registers. Are they used other
than when following the (old) calling convention? I would like to get rid of
these register stacks. In their place I would like to introduce a context
object (call it a continuation?) that saves and restores the stacks
(user_stack, pad_stack, control_stack, and intstack) and the last half of
the registers: P16-P31, I16-I31, etc. (These registers are not involved in
the calling or returning convention.) This would make it unnecessary to put
a saveall and a restoreall around each call/callcc. Of course it would still
be possible to save and restore individual registers on the user stack.

Calling a subroutine would look like (note: no saveall/restoreall needed)

set P0, ...  # put Sub PMC in place
callcc   # creates a context object
 # invokes the sub in P0

or for tail calls and other fancy stuff

set P0, ...  # put Sub PMC in place
set P1, ...  # put some context in P1 (unless it
 # is already in place as it would
 # be for most tail calls)
call # invokes the sub in P0, the current
 # context is not saved

returning looks like

  sub:
# put return values in registers ...
return   # invokes context in P1, which
 # restores context etc

or even just

  sub:
# put return values in registers ...
call P1  # same as return

Just to be clear my current implementation does most of this, except that
none of the registers are saved as part of the context, just the stacks
(including the register stacks). So my proposal is to get rid of the
register stacks and have the context object save (and restore) *half* of the
registers in addition to the user, pad, control and int stacks.

This seems like a nice approach to me as it simplifies the Parrot_Context
struct and the calling and returning from subs and methods.

Comments?

--
Jonathan Sillito



RE: Method calling

2003-05-31 Thread Jonathan Sillito
Dan,

Why is there a callmeth op? Can't we just use a regular invoke as with other
subs? Or does the callmeth op do both a find and invoke as an optimization?

Jonathan Sillito

 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]

 Nope, not objects, but at least it's partway there. This bit is about
 making method calls.

 We've two issues on the front end. First, we need to be able to get a
 method PMC from an object, in those cases where we want to save that
 for later, and second we need to call methods. So, here's how we're
 going to do it.

 We add three ops, findmeth, callmeth and callmethcc. (The latter just
 automatically takes a continuation for the following op and stashes
 it in P2, while the former assumes one has been put in P2 already)
 They all find a method PMC based on the object and method name
 already loaded. The call ops then call
   that PMC's invoke vtable entry, which acts as normal.

 So the sequence is:

 P0 = P2-find_method(interpreter, P2);

 and for the call ops, then:

 dest = P0-invoke(interpreter, P0, expr NEXT());
 goto ADDRESS(dest);

 The returned method PMC handles anything fancy--multimethod dispatch
 and whatnot. We need base engine support for MMD and method caching,
 amongst other things, but we can get to that later.

 The method PMC returned by findmeth can be invoked as a regular
 subroutine, so we're fine there. I'm not, at the moment, leaning
 towards a separate invoke this pre-fetched PMC sub as a method op,
 since we're not passing on any information as to how a PMC is invoked
 outside of there being an object in P2, but I can be convinced
 otherwise if we can make a good case for languages actually using
 that information.

 I'm thinking at this point, since we need to add the call and callcc
 ops as it is, that we should probably have tail versions of all these
 ops, which just puts the various bits from the continuation in P1
 back before making the call, but we can talk about that later if we
 want.
 --
  Dan

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




RE: Method calling

2003-05-31 Thread Jonathan Sillito
Thanks Dan. One little picky thing what is the naming convention for ops?

  find_method (currently in core.ops),
  call_method, and
  call_method_cc (or callcc_method?)

or

  findmeth,
  callmeth, and
  callmethcc (or callccmeth?)

or

  findmethod,
  callmethod, and
  callmethodcc (or callccmethod?)

Also, should the current 'invoke' op be changed to 'call'? I don't care
exactly what the names are, but consistency is nice.

Jonathan

 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]

 At 9:20 AM -0700 5/30/03, Jonathan Sillito wrote:
 Dan,
 
 Why is there a callmeth op? Can't we just use a regular invoke
 as with other
 subs? Or does the callmeth op do both a find and invoke as an
 optimization?

 It does a find and invoke, and the callmethcc does a find,
 cc-capture, and invoke.

 I'm not sure if there'll be much win, but it is more information
 available to analyzers, so they *know* that this is a method call
 rather than a random sub call.

 I figure the vast majority of the method calls most languages make
 will be either callmeth or callmethcc calls, so it makes sense to wad
 up the functionality in a single op.

-Original Message-
   From: Dan Sugalski [mailto:[EMAIL PROTECTED]
 
   Nope, not objects, but at least it's partway there. This bit is about
   making method calls.
 
   We've two issues on the front end. First, we need to be able to get a
   method PMC from an object, in those cases where we want to save that
   for later, and second we need to call methods. So, here's how we're
   going to do it.
 
   We add three ops, findmeth, callmeth and callmethcc. (The latter just
   automatically takes a continuation for the following op and stashes
   it in P2, while the former assumes one has been put in P2 already)
   They all find a method PMC based on the object and method name
   already loaded. The call ops then call
 that PMC's invoke vtable entry, which acts as normal.
 
   So the sequence is:
 
   P0 = P2-find_method(interpreter, P2);
 
   and for the call ops, then:
 
   dest = P0-invoke(interpreter, P0, expr NEXT());
   goto ADDRESS(dest);
 
   The returned method PMC handles anything fancy--multimethod dispatch
   and whatnot. We need base engine support for MMD and method caching,
   amongst other things, but we can get to that later.
 
   The method PMC returned by findmeth can be invoked as a regular
   subroutine, so we're fine there. I'm not, at the moment, leaning
   towards a separate invoke this pre-fetched PMC sub as a method op,
   since we're not passing on any information as to how a PMC is invoked
   outside of there being an object in P2, but I can be convinced
   otherwise if we can make a good case for languages actually using
   that information.
 
   I'm thinking at this point, since we need to add the call and callcc
   ops as it is, that we should probably have tail versions of all these
   ops, which just puts the various bits from the continuation in P1
   back before making the call, but we can talk about that later if we
   want.
   --
Dan
 
   --it's like
 this---
   Dan Sugalski  even samurai
   [EMAIL PROTECTED] have teddy bears and even
  teddy bears get drunk
 


 --
  Dan

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




RE: Method calling

2003-05-31 Thread Jonathan Sillito
Calling convention says that before a sub/method is invoked:

- P0 Holds the object representing the subroutine.

- P1 Holds the continuation for the caller, assuming this sub was called
with callcc. Otherwise NULL.

- P2 Holds the object the sub was called on. (For method calls)

Or put another way P2 is the receiver object. So I guess this was a typo;
the continuation should be stashed in P1.

While I am at it, here is an **untested** implementation of the call_method
op. I don't want to send a patch since I am not sure how to test this yet
(since no PMCs respond to find_method).

op call_method(in STR) {
  opcode_t *dest;
  /* assumes receiver object is in P2 */
  PMC* receiver = interpreter-ctx.pmc_reg.registers[2];
  PMC* method = receiver-vtable-find_method(interpreter, receiver, $1);

  /* calling convention says that method should be in P0 and name in S0 */
  interpreter-ctx.pmc_reg.registers[0] = method;
  interpreted-ctx.string_reg.registers[0] = $1;

  dest = (opcode_t *)method-vtable-invoke(interpreter, method, expr
NEXT());
  goto ADDRESS(dest);
}

op call_method(in PMC, in STR) {
  opcode_t *dest;
  PMC* method = $1-vtable-find_method(interpreter, $1, $2);

  /* calling convention says that receiver should be in P2 and method in P0
*/
  interpreter-ctx.pmc_reg.registers[0] = method;
  interpreter-ctx.pmc_reg.registers[2] = $1;
  interpreted-ctx.string_reg.registers[0] = $2;

  dest = (opcode_t *)method-vtable-invoke(interpreter, method, expr
NEXT());
  goto ADDRESS(dest);
}

--
Jonathan Sillito

 -Original Message-
 From: Nicholas Clark [mailto:[EMAIL PROTECTED] Behalf Of Nicholas
 Clark

 I'm not sure if I'm asking a stupid question here, but:

 On Fri, May 30, 2003 at 08:12:34AM -0400, Dan Sugalski wrote:

  We add three ops, findmeth, callmeth and callmethcc. (The latter just
  automatically takes a continuation for the following op and stashes
  it in P2, while the former assumes one has been put in P2 already)

 You say P2 is a continuation

  They all find a method PMC based on the object and method name
  already loaded. The call ops then call
that PMC's invoke vtable entry, which acts as normal.
 
  So the sequence is:
 
  P0 = P2-find_method(interpreter, P2);

 But you seem to be using P2 like it's the object
 I'm confused.
 Surely there are 3 things to play with - object, method name and
 continuation to return to? If so, are they P0, P1 and P2 before these
 ops?

 Nicholas Clark




RE: coroutines end and DFG

2003-03-04 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]

 Does a couroutine end? And how?
 The current implementation jumps forth and back by the Binvoke opcode,
 one is a call coroutine the other is a yield. There seems to be no
 possibility, that the coroutine states, I'm finished now - with
 possibly meaning don't call me again.

That's correct.

 And from imcc's register allocations POV the whole coroutine stuff is a
 PITA, no registers are preserved, AFAIK, so a coroutines and the caller
 + all edges out from both do share the same registers, don't they?

They do, except that each coroutine has its own user stack so saveall and
restoreall can work properly.

-- jonathan sillito



RE: Three questions

2003-02-10 Thread Jonathan Sillito
 -Original Message-
 From: Kevin Reid [mailto:[EMAIL PROTECTED]]
 
 0. PDD 3 says:
 
 P1  
Holds the continuation for the caller, assuming this sub was
 called with callcc. Otherwise NULL. 
 
and implies a similar possible absence for P2. How does one ensure
 that a PMC register is 'NULL'? One other example language compiler
 implies that there is no(t yet) an op for this.
 
 1. Is there a complete example (e.g. multiple lexically nested
 subroutines using the full PDD3 calling conventions) of how the pad
 operations are intended to be used?

Some examples are in:

  examples/assembly/lexical.pasm
  examples/assembly/lexical2.pasm
  t/op/lexicals.t
  t/pmc/scratchpad.t
  t/pmc/sub.t

These are probably not sufficient, I still intended (this week 
I hope) to post a how to document for the lexical stuff.
 
I've implemented what appears to be appropriate usage based on
 examination of t/pmc/sub.t and core_ops.pod, but it is not exhibiting
 proper closure behavior - all subs share the same state.

Would you like to post your code? Then we can figure out if 
you have found a bug or if we just need to clarify how to 
use the lexical ops etc.
 
-- jonathan




RE: Objects, methods, attributes, properties, and other related frobnitzes

2003-02-03 Thread Jonathan Sillito
 -Original Message-
 From: Andy Wardley [mailto:[EMAIL PROTECTED]]On Behalf Of Andy Wardley
 
 Dan Sugalski wrote much sense, including these gems:
  *) Method: Some sort of action that an object can do. Methods are 
  global and public--only one foo method for an object. Methods may be 
  inherited from parent classes, or redefined in a particular class. 
  Redefined methods hide parent class methods of the same name
 
 What about redefining methods for a particular object instance?
 
 It's something that Ruby does and can be extremely useful.

Behind the scenes ruby creates a new (anonymous) subclass,
which contains the new method.

-- jonathan



RE: Objects, finally (try 1)

2003-01-15 Thread Jonathan Sillito
I realize this will vary from language to language, but generally we will
need a PMC that encapsulates a method (and responds to the invoke vtable
method like Sub, or maybe the Sub PMC could do?). This python code is
interesting:

class A:
  def f (self):
print A.f()

def g (self):
  print g()

a = A()
a.f()# output: A.f()

x = a.f  # get the method, a limited form of currying
 # since the first arg (a==self) is stored
x()  # output: A.f()

setattr(A, f, g)  # replace A's f with g

a.f()# output: g()
x()  # output (still): A.f()  !!!

Which shows that the dispatch (i.e. selecting which method to call) can
happen before the invocation.
--
Jonathan Sillito

 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]]

 At 8:53 PM -0800 1/14/03, Adriano wrote:
 On Tue, 14 Jan 2003 17:18:22 -0500, Dan Sugalski [EMAIL PROTECTED] wrote:
 
 Dan:
 You're off. It'll be something like:
 
 callmethod Px, method_name
 
 or
 
 jmpmethod Px, method_name
 
 Jonathan:
 Is there going to be any way to (in PASM) find a method with
 out invoking
 it? I am not sure, but it may be useful for currying and some efficiency
 stuff (like moving dispatch outside of a loop that repeatedly invokes a
 method).
 
 Dan:
 Yep. There should be a can operator, though I'm not sure how often
 one wants to check for the existence of a method in an object
 without calling it. But no reason not to. More for rev 2.
 
 I think what Jonathan asked for was an operator for returning a
 method (as an object) which can be invoked later with some arguments
 (or even applied with a partial list of arguments for currying).
 This would be a lot more useful than a yes-or-no answer about
 the existence
 of a method.

 I thought about this--it's what the find_method vtable method was for
 in the first place. Unfortunately, as was pointed out to me, there's
 no good way to cache the result, since it could potentially be wrong
 by the time the method is actually called.

 We could potentially get around this if we put in place a
 notification framework to invalidate these method handles, but that
 means we have to have a fair amount of infrastructure in place to do
 that. (Though, honestly, I do really like the idea, as it means we
 can be faster by default and just pay the price when things change,
 but there's that pesky code that needs writing and systems that need
 designing to support it...)
 --
  Dan

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





RE: Objects, finally (try 1)

2003-01-15 Thread Jonathan Sillito
Sounds like we want objects *and* classes to support:

static_attribs - which are defined at compile time and
accessed by offset probably stored in an array.

dynamic_attribs - which come and go at run time and are
generally accessed by name and likely stored in a hash.

--
Jonathan Sillito

 -Original Message-
 From: Nicholas Clark [mailto:[EMAIL PROTECTED]]
 Sent: January 15, 2003 12:41 PM
 To: Dan Sugalski
 Cc: Gopal V; [EMAIL PROTECTED]
 Subject: Re: Objects, finally (try 1)


 On Wed, Jan 15, 2003 at 11:17:17AM -0500, Dan Sugalski wrote:
  In that case they'd correspond to our properties, and I can already
  feel a massive terminology disconnect looming. Maybe we should rename
  properties and attributes to frobs and thingies, just so there's no
  overlap. :(

 We could call them houses and hotels -  you'd only be allowed attributes
 after you had 4 properties, and if you want to mortgage, er serialise the
 object you'd have to hand them all back to the bank, er GC system.

 Mmm. Maybe that's taking the analogy well beyond breaking point.

 I've had a look in a thesaurus for words similar to property and
 attribute,
 and I can't see much that's good. idiosyncrasy is a nice word,
 but it's 6
 syllables, and hard to spell. satellite seems quite good for objects and
 stuff that are hangers-on, as does chattels. I quite liked the idea of
 virtue for a quality, although I'm not sure if Larry would sanction PMCs
 having vices as well :-)

 The downside of finding completely new names for these two
 concepts is that
 everyone would have to learn what they meant. The upside is that
 there would
 be no confusion with every other language's contradictory definitions.

 Nicholas Clark





RE: Objects, finally (try 1)

2003-01-14 Thread Jonathan Sillito
Dan,

Below are some questions about this ...

 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]]

[snip]

 Objects, as far as I see it, have the following properties:

 1) They have runtime-assignable properties

Terminology question: what is the difference between a property and an
attribute? Perhaps the answer could go in the glossary.

[snip]

 #3 Since each class has a PMC type, we just need to associate the PMC
   type with the data a class needs. Also pretty much no big deal, and
   something we already have facilities for.

So, while there may be exceptions, generally all classes will be instances
of the Class PMC, true?

[snip]

 The call/jmpmeth opcodes either make a returnable or non-returnable
 method call. They fetch the function pointer from the object PMC and
 either dispatch to it or save the current state and jsr to it. Note
 that you can't jmpmeth into a C-implemented method, so no tail
 calling into those without some wrapper opcodes. The registers still
 need to be set up appropriately, just like with a regular sub call.

So the call opcode takes a method name or offset and calls a vtable method
to find the method and then invokes it?

 The find_method vtable entry should die, and be replaced with a plain
 method entry. This should return either the address of the start of
 the method's bytecode, or NULL. The NULL return is for those cases
 where the method actually executed via native code, and thus doesn't
 have to go anywhere. If an address is returned it's expected that the
 engine will immediately dispatch to that spot, obeying parrot's
 calling conventions.

Not sure what this means, does it mean that there is a method named
find_method accessed something like

  call Px, Py, find_method

which I can then call to find the method or am I off?

[snip]

 The structures:

 *) Attr PMCs have an array off their data pointer.

 *) Classes are variants of Attr PMCs. They have the following
   guaranteed attributes in slots:

 0) Hash with class name to attribute offset

I am not sure what this means, Don't we already have the class and it's
attributes if we are accessing these slots?

 1) Hash with attribute name to attribute offset (relative to the
offset found from the hash in slot 0, generally known at
compile time, but introspection is nice)
 2) Integer number of attributes this class has
 3) Notification array

Do we store ptrs to parent classes in one of these slots? Also Can I access
slots like:

  set Px, Py[1]# store the name to offset hash in Px

[snip]

So to sum up we need the following pmc's:

  pmclass Ref {
data is a pointer to an object
  }

  pmclass Attr {
data is an array of attributes
  }

  pmclass Class extends Attr {
  }

  pmclass Object {
this was not explained, but I guess it at least
has a reference to a Class and field data ???
  }

Does that cover it?
--
Jonathan Sillito




RE: Objects, finally (try 1)

2003-01-14 Thread Jonathan Sillito
 -Original Message-
 From: Dan Sugalski [mailto:[EMAIL PROTECTED]]

 A property is a runtime assignable name/value pair that you stick on
 a variable or value. An attribute is a named variable that all
 objects of a particular class have.

 Properties can come and go at runtime, but attributes are fixed. (I
 think you could also consider attributes instance variables, but
 I'm a bit OO fuzzy so I'm not sure that's entirely right)

Ok, in the case of python or ruby, instance variables are not fixed and they
are not declared as part of the class. I suppose this can be handled by
giving such classes one hash attribute for storing these instance variables.

 You're off. It'll be something like:

 callmethod Px, method_name

 or

 jmpmethod Px, method_name


Is there going to be any way to (in PASM) find a method with out invoking
it? I am not sure, but it may be useful for currying and some efficiency
stuff (like moving dispatch outside of a loop that repeatedly invokes a
method).

 Do we store ptrs to parent classes in one of these slots? Also
 Can I access
 slots like:
 
set Px, Py[1]# store the name to offset hash in Px

 No the parent's gotten to via the vtable, and yes you can.

Sorry if this is obvious, but which vtable method is used to get the
parents?

Thanks!
--
Jonathan Sillito




RE: [CVS ci] clone, dod stack reporting

2003-01-10 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:[EMAIL PROTECTED]]

 Further remark: the scratchpad clone code looks dubious, the 2 lists in
 the data (lex) entry should probably cloned too - and at least the lex
 ptrs themselves.
 The destroy method leaks, because we can't cleanup duplicated lex ptrs.

 Can somone better knowing scratchpads comment on this please.


I guess there is a related problem with the way the function scratchpad new
works, since it needs to copy lex ptrs from enclosing scopes?

I will look into it more in a bit ...

--
Jonathan Sillito




RE: [PATCH] [CVS ci] clone, dod stack reporting

2003-01-10 Thread Jonathan Sillito
The attached patch fixes the problem. It changes Scratchpad's data pointer
to be a pointer to an array of Parrot_Lexicals (rather than an array of
pointers to Parrot_Lexicals). The (name and value) lists are shared but
never the actual Parrot_Lexical ptr. So no more leak.

Patch touches:

 -- classes/scratchpad.pmc
 -- sub.c
 -- t/pmc/scratchpad.t (adds a test)

--
Jonathan Sillito

 -Original Message-
 From: Jonathan Sillito [mailto:[EMAIL PROTECTED]]

  -Original Message-
  From: Leopold Toetsch [mailto:[EMAIL PROTECTED]]
 
  Further remark: the scratchpad clone code looks dubious, the 2 lists in
  the data (lex) entry should probably cloned too - and at least the lex
  ptrs themselves.
  The destroy method leaks, because we can't cleanup duplicated lex ptrs.
 
  Can somone better knowing scratchpads comment on this please.
 

 I guess there is a related problem with the way the function
 scratchpad new
 works, since it needs to copy lex ptrs from enclosing scopes?

 I will look into it more in a bit ...





scratchpad_leak.patch
Description: Binary data


RE: [perl #18170] [PATCH] very complete lexical scope implementation

2002-11-18 Thread Jonathan Sillito
 -Original Message-
 From: kj [mailto:[EMAIL PROTECTED]]

   I'm getting mixed results building from this morning's CVS -- on
 Linux/x86 I only get the t/op.lexicals.t failures, but on Darwin/PPC I'm
 also getting failures in t/pmc/scratchpad.t.  Would your patch have
 anything to do with the latter?  I'm still learning the internals, and
 haven't quite figured that out yet.

With a fresh checkout I am getting no errors in Linux/x86, however I don't
have access to a Darwin/PPC box. Would you mind getting the latest from CVS
and try again on Darwin/PPC? As much detail as you can send me about any
failures would be appreciated.

Thanks.
--
Jonathan Sillito




RE: [perl #18170] [PATCH] very complete lexical scope implementation

2002-11-15 Thread Jonathan Sillito
Steve,

Thanks! Was there a problem applying the patch? I just checked out a new cvs
images and the file t/op/lexicals.t has not been updated. As a result, a few
tests are failing. Should I resubmit the part of the patch that updates
t/op/lexicals.t?

--
Jonathan Sillito

 -Original Message-
 From: Steve Fink [mailto:steve;fink.com]
 Sent: November 14, 2002 9:51 PM
 To: [EMAIL PROTECTED]
 Subject: Re: [perl #18170] [PATCH] very complete lexical scope
 implementation


 Applied, finally. Thanks.





RE: [purl #18379] [PATCH] Lexical scope and functions in languages/scheme

2002-11-14 Thread Jonathan Sillito
 -Original Message-
 From: Dan Sugalski [mailto:dan;sidhe.org]

 At 2:07 PM + 11/14/02, Jürgen Bömmels (via RT) wrote:
 This patch obsoletes #17109 (which isn't applied yet).

 Does it obsolete 18170?

No, it seems to depend on it.

 -Original Message-
 From: Jürgen Bömmels (via RT)

 DEPENDS ON #18170

[... reordered ...]

 One thing I'm not very happy about that I need 2 pop_pads at function
 return, one cleaning up the newly generated pad from new_pad, and one
 for cleaning up the stored scope of function definition. I have no
 idea how to solve this.

Well currently the way to return from a sub is using the ret op. It may be
useful to add a 'return' op that does one pop of the lexical stack (in
addition to doing what ret does). This would mean that a sub would only need
an explicit pop_pad for each local scope created.

However, subs that are not closures could continue using the ret op.

(So Dan, should I submit a patch adding a 'return' op?).
--
Jonathan Sillito




Re: [perl #18170] [PATCH] very complete lexical scope implementation

2002-11-04 Thread Jonathan Sillito


On 2 Nov 2002, Juergen Boemmels wrote:

 Ok, I tested the patch (I tried to use this scratchpads for the scheme
 compiler)
 One thing I missed (or at least didn't find): How can I generate a new
 scope? new_pad generates a new one one the pad stack with a size which
 is actually smaller than the current one.

I may be misunderstanding the question, but I'll try and answer anyway.
There are two ways to create a new scratchpad. The first looks like:

op new_pad(in INT)

which creates a new scratchpad and grabs to depth int of the current
scope (i.e. the scratchpad at the top of the stack). This I think will
be the usual way to create a new scope. The alternative looks like this:

op new_pad(out PMC, in INT)

which does the same as the previous form, but does not push the new pad
on the stack, rather it is stored in the given PMC register.

Does that answer your question?

 Apart from that: Nice patch.


--
Jonathan Sillito




RE: [perl #18170] [PATCH] very complete lexical scope implementation

2002-10-31 Thread Jonathan Sillito
 -Original Message-
 From: Leopold Toetsch [mailto:lt;toetsch.at]

 WRT your comment: should we use a List * here, I slightly vote for
 yes. In the long run we could use List as the basic store for registers
 and stacks as well.
 List would only need a small extension to manage arbitrary sized data.

Ok, if the code goes in I can easily change this ...

 WRT names: wouldn't be a hash faster then the linear search?

My thinking is that compilers will most often generate code that accesses
lexicals using position and the current structure provides constant time by
position access to the lexicals. While by name access is linear time. As
you say, this could be improved using a hash, but at some cost in space
(maybe?).

In any case, the implementation details of the struct Parrot_Lexicals are
(currently) only touched in sub.c, so it should be easy to change the
approach.

Thanks for the comments, anything else?
--
Jonathan Sillito




RE: Scratchpad confusion

2002-10-21 Thread Jonathan Sillito
I think, I can answer a few of these questions.

 -Original Message-
 From: Allen Short [mailto:washort;twistedmatrix.com]

 The ops described in PDD 6 and docs/parrot_assembly.pod for
 scratchpads appear to be subtly different from the ones actually in
 core.ops. In particular, i was led astray by the docs referring to the
 newpad op and core.ops implementing new_pad. which is it supposed
 to be? =)

Neither, Dan Sugalski owes us an update, which should be coming soon ...

 I started investigating scratchpads because I'm interested in
 improving the scheme compiler. I'd agree with Sean O'Rourke's comments
 (http://archive.develooper.com/perl6-internals;perl.org/msg12722.html)
 -- the current ops seem too limited; in particular, I dont see how one
 would save a scratchpad with a function definition, or modify the
 toplevel scratchpad.  Looking beyond Scheme, it appears to me that
 other languages would need more flexible handling of scoping as well;
 Common Lisp, for example, keeps functions in a separate namespace from
 other variables. Being new to Parrot hacking, could someone point me
 at the rationale for making scratchpads a special case, rather than a
 PMC?

I am sure they will be a PMC. In fact two different patches have been
submitted to make them PMCs, one by me and a better one by Sean O'Rourke.
Sean's has not been committed yet, probably because he is waiting for a
decision on the more flexible ops by Dan.

--
Jonathan Sillito




RE: [PATCH] PMC initializer stuff

2002-10-18 Thread Jonathan Sillito


 -Original Message-
 From: Dan Sugalski [mailto:dan;sidhe.org]

 Okay, it's been a while, I've been out of it, it's time to start
 getting going.

Welcome back!

 Today's first topic: PMCs with real initializers. Here's a snip from
 the updated PDD2:

 --

 =item void init_pmc(INTERP, PMC* self, PMC* initializer)

 This form of the init method takes a single initializer parameter. The
 initializer is an array that contains keys and values. The meaning of
 the keys and their corresponding values is left up to the PMC.

Then I assume that the op new_pmc should be added which calls the init_pmc
vtable function? If so the patch in [perl #17811] should do the trick.

[snip]

 Dimension, 3, Color, Green]. Note that, in all cases, the array
 is an array of PMCs. (So you get either an int PMC or a string PMC in
 the list of keys)

Do you mean PerlInt and PerlString? Or do we want Int and String PMCs? In
the case of Sub PMCs an initializer could provide an address for the sub to
jump to which could look like this:

  #
  # build initializer
  #
  new P10, .Array
  set P10, 2

  new P11, .PerlString
  set P11, address

  new P12, .PerlInt
  set_addr I0, subroutine
  set P12, I0

  set P10[0], P11
  set P10[1], P12

  #
  # construct Sub using initializer
  #
  new P0, .Sub, P10
  invoke
  end

subroutine:
  print in sub routine\n
  ret

This seems tedious, but maybe I am missing the point? Anyway if this is what
we want the attached patch modifies sub.pmc to support this, and adds a test
to t/pmc/sub.t. This patch depends on [perl #17811].

--
Jonathan Sillito



sub_init.patch
Description: Binary data


RE: [perl #17739] [PATCH] Tests for assign ops

2002-10-04 Thread Jonathan Sillito

 -Original Message-
 From: Peter Gibbs [mailto:[EMAIL PROTECTED]]


[snip]

 An interesting question, not discussed when the change was
 initiated, relates to property assignments eg
   new P0, .PerlArray
   set P0, 6

 This most certainly does not set register P0 to six, so the 'set'
 opcode should not apply, but it is also not really an assignment
 either. Any thoughts?

there is a similar problem with subs

  new P0, .Sub
  set P0, some label

I guess the problem is that set is being used for too much? 
This is the way I thought things were headed: set_x_x just 
moves a pointer or a value, possibly needing a cast, copy or
conversion

  $1 = $2;
  $1 = string_from_num($2);
  etc

While assign_p_x calls the appropriate vtable method

  $1-vtable-set_pmc(interpreter, $1, $2);
  $1-vtable-set_integer_native(interpreter, $1, $2);
  etc

The above .Sub and .PerlArray examples could be handled 
with

  op new(out PMC, in INT, in PMC)
  op new(out PMC, in INT, in INT)
  etc

instead of the set op. I think this separation could be 
more clear, but I suppose this leaves some cases out. So
maybe a set_property op? Though some things could be left
to _methods_ instead of ops.

--
Jonathan Sillito

 
 The primary goal of the exercise was to be able to distinguish
 between 'set P0, P1' which simply sets the P0 register equal to
 the P1 register, and 'assign P0, P1' which would, somehow,
 cause the existing PMC referenced by P0 to acquire the value
 of the PMC referenced by P1 (via the vtable method set_pmc).
 How to achieve this has never been resolved. The changes of
 the other 'set P0, xxx' opcodes to 'assign' are basically for
 consistency.
 --
 Peter Gibbs
 EmKel Systems
 





RE: pre-PATCH: functions in languages/scheme

2002-09-25 Thread Jonathan Sillito

 -Original Message-
 From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]]

 The current pad_stack handling is very much tied to Sub.pmc. The only
 way of getting the current scope is creation of a new sub; the only
 way setting the current pad is invoking this sub.

 But I didn't used Sub.pmc, partly because the lexical scope is not
 working in CVS subs and i don't want to add yet another set of
 prepatches, partly because I added the formal parameters to the
 procedure object. So I think there are two possible ways out: adding
 operations to core.ops (get_current_pad_p and new_pad_p) or rolling the
 lexical pad on my own.


It would be nice if parrot provided the lexical scope semantics scheme (and
other languages) needs rather than have each language implement their own. I
guess this would be Dan's call, but just as another suggestion, could the
lexical ops be limited to something like the following, plus keyed access to
the pad?

  new Px, .ScratchPad
  push_pad Px
  peek_pad Px
  pop_pad Px

(The find_lex and store_lex ops would be unnecessary, but could be kept of
course)

 And there is a diffrence between define and set!, define creates a new
 binding in the top lexical scope, ignoring every previous definition,
 but set! changes the binding of a formerly defined variable. This 2
 diffrent operations don't map very well on the store_lex_s_p
 operation. I used the diffrent keyed access methods of Seans
 Scratchpad.pmc for differentating this use cases:
 define : P31[-1;S0]
 set!   : P31[S0]


Assuming Sean's patch (not my above suggestioned ops), would this implement
the correct semantics for scheme's (define a ...):

  new_pad 1
  new P0, .SchemeUndef
  store_lex 1, a, P0
  # ...
  pop_pad

and could (set! a 12) inside of the above define be:

  new P0, .SchemeInteger
  store_lex a, P0  # looks back through nested pads

--
Jonathan Sillito




RE: pre-PATCH: lexicals

2002-09-23 Thread Jonathan Sillito

 -Original Message-
 From: Piers Cawley [mailto:[EMAIL PROTECTED]]
 Jonathan Sillito [EMAIL PROTECTED] writes:
  get_counter:
  new_pad 1

 Doesn't this violate the 'caller saves' principle, making it hard to
 do tail call optimization? Would it make sense to move the creation of
 a new pad into the Sub's invoke method?


I am not sure how this violates the 'caller saves' principle, unless you
mean that the caller should be saving its own scratch pad if necessary? I
did notice that this is in pdd03:

The caller is responsible for preserving any environment it is
interested in keeping. This includes any and all registers, lexical
scoping and scratchpads, opcode libraries, and so forth.

I suppose scratchpads could be an exception, to this?

I have to think more about the tail call optimization. I am not sure how
putting the creation of the new pad into the sub's invoke method would help,
it still seems like it would be created each time the method was invoked
(which seems equivalent to putting a new_pad instruction at the top ... On
the other hand, if the instruction is left to the PASM for some subs it
could easily be optomized away by the compiler. Or maybe it could be
conditional?

  get_counter:
new_pad 1
  get_counter_no_new_pad:
# etc

Would this address the problem? Or am I missing somthing?
--
Jonathan Sillito




Re: [perl #17030] [PATCH] Implementation of Lists for languages/scheme

2002-09-10 Thread Jonathan Sillito

Sorry if this comment is out of context, I am behind but catching
up. The patch in [perl #16797] adds a scratchpad pmc (among other
things). Hopefully it is not too far out of date to apply. I
believe Melvin is looking into it ...

--
Jonathan Sillito

On Tue, 10 Sep 2002, Piers Cawley wrote:

 Juergen Boemmels [EMAIL PROTECTED] writes:

  Piers Cawley [EMAIL PROTECTED] writes:
  { type = '*environment*' value = {scratchpad = aScratchPadPMC}
 
  There is already a ScratchPadPMC. Where is it? It's not in classes/,
  is it. As a first implementation a PerlHash is sufficent, (I actually
  have a patch doing exactly this, it just needs a little polish. Maybe
  I will submit it tomorrow). But most of the lexical scope can resolved
  at compile time. parrot_assembly.pod describes an op fetch_lex_p_i_i
  but this seems not implemented yet.





Re: Lexicals

2002-09-10 Thread Jonathan Sillito

I am not the best one to answer these questions, but I will
make some comments anyway, though Dan is/was planning to give
us an authoritative position doc on some of these issues.

I have done some work on some of this, but my latest code
submission has not been accepted yet.

On 9 Sep 2002, Juergen Boemmels wrote:

 I have several questions regarding lexicals.

 There is a discrepancy between parrot_assembly.pod and core.ops
 parrot_assembly.pod says that find_lex will return a pointer, where as
 core.ops uses find_lex to retrive a value and store_lex to set this
 value. Which of this is correct?


I would think it will become pointers.

 parrot_assembly mentions a fetch_lex_p_i_i but there is no
 implementation yet. This functions would be very handy when you know
 at compile time whats in the lexical scope. Is this left-out
 intentional or just because nobody has yet implemented it. In the
 later case, is somebody already working on this?


This is still the plan and I believe that by index is going to
be the fastest way to access lexicals. I have been thinking about
implementing something for this but I am waiting to see if my
previous patch gets committed so I can be sure I am heading in a
reasonable direction. On the other hand maybe I should just press
forward?

 How are the integers of the lexicals in the pad assigned? I assume
 they get increasing numbers for each store_lex, starting at 0 for a
 new pad. Correct?

 How do I store to a lexical by number? Shouldn't be there also a
 store_lex_i_i_p (or set_lex to indicate that it is a change of an
 already existing binding).

Dan has hinted that there will be some way, in parrot assembly,
to provide a static pad descriptor that could be used to put all
lexicals in place when the pad is first created.

 Is there a possibility to get a pointer to the current pad, to store
 it in the closure? (Im not sure, maybe only the top-pad is needed).
 There need also be a way to reinstate the saved lexical.

I have submitted code that does this sort of thing for
subroutines.

--
Jonathan Sillito




Re: A show of hands of the non-perl people?

2002-09-04 Thread Jonathan Sillito

On Wed, 2002-09-04 at 04:31, Dan Sugalski wrote:
 Can I get a quick show of hands for the folks working on Parrot, even 
 peripherally, who *aren't* perl folks? 

I am not a perl person. I haven't done much work on parrot, and it seems
that most of what I have done is on hold or up in the air still (my
patch in [perl #16797] for example). But I am hoping to somehow get more
involved.

Also, for what it is worth, I personally don't much care what the email
list is called.
--
Jonathan Sillito



Re: [COMMIT] GC_DEBUG, Some GC Fixes, and Remaining GC Bugs

2002-08-12 Thread Jonathan Sillito

Mike,

I tried to have a look at the lexicals and subs issues but I am finding
that with the GC_DEBUG flag set to 1, I *always* get a segmentation
fault, even for simple pasm files like :

  set I0, 12
  end

or just:

  end

Is there something I am doing wrong? I did a fresh checkout about an
hour ago.

???
---
Jonathan Sillito



On Mon, 2002-08-12 at 01:56, Mike Lambert wrote:
 Hey,
 
 I re-added the GC_DEBUG define today, and weeded out a bunch of issues.
 For those who don't remember, GC_DEBUG (currently in parrot.h) causes
 various limits and settings and logic to be setup such that GC bugs occur
 relatively soon after the offending code. It allocates one header at
 a time, and performs DOD and collection runs extremely frequently
 (effectively, anywhere they could possibly occur if GC_DEBUG weren't
 defined.) It's goal is to make GC bugs which appear only in complex
 programs...appear in simpler ones as well.
 
 Check the cvs-commit traffic if you're interested in what issues I've
 fixed already. From what I can tell, two things remain:
 - regexes (these are known to be broken. angel's latest patch should fix
 these in theory. Probably not worth spending time on fixing these.)
 - hashes (these were recently rewritten to use indices, a step forward,
 but they aren't 100% clean yet)
 - lexicals (there's one remaining issue on the last test I didn't look
 into)
 - subs (likely includes all variety of them. Basically, I got the wrong
 result on one test, instead of GPF failures like I received on the above
 bugs.)
 - possibly other that got lost in the noise of the above issues
 
 Anyone more well-versed in these departments than I care to take a look at
 the potential problems? Just change GC_DEBUG in parrot.h, and you can be
 on your way. :)
 
 Thanks,
 Mike Lambert




Re: [perl #16087] [PATCH] Scratchpad pmc

2002-08-12 Thread Jonathan Sillito

Dan, some time ago you mentioned that you were preparing a position doc
on issues raised in the 'maybe-PATCH: sub/continuation/dlsym/coroutine
clean-up' thread. Are you nearly ready with that doc? Does this patch
(i.e. a scratchpad pmc) fit into what you have in mind? 

Sorry to be harassing you about this, but I am anxious to do more coding
and I just want to be sure that I am moving in roughly the right
direction ...

... well, while I am already harassing you two, I'll try a few questions.

1) The Parrot_Sub struct in sub.h has its own user_stack and
control_stack. Why is this necessary?

2) If they are necessary, then does that mean the caller needs to save
and restore their user_stack and control_stack?

3) Some of the caller save burden (and overhead?) could be minimized if
there was 'ret' vtable method that was called to do some clean up ... ok
so that is not a question just some random thought.

4) Parrot_Coroutine's 'init' is not longer used and can go away, I guess
I could remove it in a future patch ... ok so that's not a question
either.

Anyway, thanks for any info!
--
Jonathan Sillito


On Thu, 2002-08-08 at 14:29, Jonathan Sillito wrote:
 # New Ticket Created by  Jonathan Sillito 
 # Please include the string:  [perl #16087]
 # in the subject line of all future correspondence about this issue. 
 # URL: http://rt.perl.org/rt2/Ticket/Display.html?id=16087 
 
 
 The main purpose of this patch is to give scratchpads a pointer to their
 parent pad. In the process I added a Scratchpad pmc that uses its data
 pointer to point to a PerlHash (temporarily) and uses its cache pointer
 to point to its parent. I am not sure about this use of the cache
 pointer, but it is only used internally so it should be easy to change.
 
 The scratchpad.pmc file is attached, the important bits (so far) are the
 init(), mark(), set_pmc_keyed() and get_pmc_keyed() vtable methods.
 
 The attached patch has the following effects:
 
 - changes lexical ops in core.ops to use Scratchpad pmc.
 - adds Scratchpad to enum in include/parrot/pmc.h
 - adds Parrot_Scratchpad_class_init(enum_class_Scratchpad); to
 global_setup.c
 - adds additional test to t/op/lexicals.t
 - fixes examples/assembly/lexicals.pasm (reverses PMC and string
 arguments to store_lex op).
 
 MISSING
 ---
 
 Access by integer index, I am waiting for a way to pass a pad descriptor
 (or at least the number of lexicals to go in the pad) to the init vtable
 method.
 
 There is no integration with subs/coroutines/continuations. I will add
 this if people think this approach is reasonable.
 
 Comments?
 --
 Jonathan Sillito
 
 
 
 -- attachment  1 --
 url: http://rt.perl.org/rt2/attach/33293/27417/874baa/lexicals.patch
 
 -- attachment  2 --
 url: http://rt.perl.org/rt2/attach/33293/27418/a51da2/scratchpad.pmc
 
 
 

 Index: core.ops
 ===
 RCS file: /cvs/public/parrot/core.ops,v
 retrieving revision 1.195
 diff -u -r1.195 core.ops
 --- core.ops  7 Aug 2002 04:01:24 -   1.195
 +++ core.ops  8 Aug 2002 20:19:54 -
  -3662,8 +3662,8 
  =cut
  
  op new_pad() {
 -PMC* hash = pmc_new(interpreter, enum_class_PerlHash);
 -stack_push(interpreter, interpreter-ctx.pad_stack, hash, 
STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
 +PMC * pad = pmc_new(interpreter, enum_class_Scratchpad);
 +stack_push(interpreter, interpreter-ctx.pad_stack, pad, 
STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
  
  goto NEXT();
  }
  -3674,24 +3674,22 
  }
  
  op store_lex(in STR, in PMC) {
 -PMC * hash = NULL;
 +PMC * pad;
  KEY key;
  Stack_entry_type type = 0;
  MAKE_KEY(key, $1, enum_key_string, struct_val);
 -hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type);
 -hash-vtable-set_pmc_keyed(interpreter, hash, NULL, $2, key);
 +pad = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type);
 +pad-vtable-set_pmc_keyed(interpreter, pad, NULL, $2, key);
  goto NEXT();
  }
  
  op find_lex(out PMC, in STR) {
 -PMC * hash = NULL;
 +PMC * pad;
  KEY key;
  Stack_entry_type type = 0;
  MAKE_KEY(key, $2, enum_key_string, struct_val);
 -hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type);
 -$1 = hash-vtable-get_pmc_keyed(interpreter, hash, key);
 -
 -/* FIXME: should the not found case be an internal_exception ? */
 +pad = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type);
 +$1 = pad-vtable-get_pmc_keyed(interpreter, pad, key);
  
  goto NEXT();
  }
 Index: global_setup.c
 ===
 RCS file: /cvs/public/parrot/global_setup.c,v
 retrieving revision 1.31
 diff -u -r1.31 global_setup.c
 --- global_setup.c4 Aug 2002 22:54:31 -   1.31
 +++ global_setup.c8 Aug 2002 20:19:54 -
  -34,6

Re: questions about pdd03_calling_conventions.pod

2002-08-09 Thread Jonathan Sillito

On Tue, 2002-08-06 at 20:11, Sean O'Rourke wrote:
 On Tue, 6 Aug 2002, Dan Sugalski wrote:
 
  At 12:57 PM -0600 8/6/02, Jonathan Sillito wrote:
  Can a prototyped sub take a variable number of parameters (ie can it
  have 'rest' params?). If so, should there be some way for the caller to
  specify how many params are being passed in pmc registers?
 
  A prototyped sub can take a variable number of params, and there
  should be a counter somewhere. I thought that was specified, but
  apparently not. I'll fix that.
 
 I'm guessing this would be:
 
 I1  The number of items pushed onto the stack.

Though I think what is missing is the number of PMC's passed in
registers.

  The pdd mentions callcc, but the callcc op seems to be going away
  (replaced with invoke on a continuation pmc) ... is that the plan?
 
  Callcc needs to stay--its removal is an oversight.
 
 Does it?  We can do the same thing (and other, more devious ones) with
 existing ops.  From my understanding of pdd03, the exact implementation
 would be this:
 
 # P0 contains a function object
   new P1, .Continuation
   set_addr I4, L1
   set P1, I4
 # Setup rest of args
   invoke
 L1:

I like it. What do you think Dan?
--
Jonathan Sillito



Re: Lexical variables, scratchpads, closures, ...

2002-08-02 Thread Jonathan Sillito

On Fri, 2002-08-02 at 10:43, Jerome Vouillon wrote:
 Sure, you need a hash.  But this can be a statically allocated hash,
 mapping variable names to indices.

Could two parallel arrays work? One stores the lexicals (accessed by
index) and the other stores the names of the lexicals. Then to access a
lexical by name involves a sequential search through the (probably not
large) array of names, to get the index, then the index is used to get
the lexical from the other array.

Or would that make access by name too slow?
--
Jonathan Sillito



Re: maybe-PATCH: sub/continuation/dlsym/coroutine clean-up

2002-08-01 Thread Jonathan Sillito

Looks good to me. Couple of quick things, when I applied the patch
locally, it indented the end bracket of the invoke op in core.ops which
breaks ops2c.pl. Also the patch removed the yield op from core.ops, was
this intentional? More comments below.

On Tue, 2002-07-30 at 22:07, Sean O'Rourke wrote:
 This patch implements native extensions and continuations as pmcs. It also
 cleans up the existing Sub and Coroutine types, and removes the following
 now-obsolete ops:
 
 callco
 callcc
 capturecc
 call
 callnative
 
 These are all handled through various uses of invoke (see t/pmc/sub.t
 for simple examples). 

I like this, then the code generator does not need to know what type of
sub it is dealing with. While I am thinking about it, would it make
sense to distinguish between a sub and a closure? A sub would be a
little more efficient in cases where a closure is not needed.

[skipping]

 - not integrated with lexicals.  Parrot is a fast-moving target nowadays!

Current discussion on the list makes me wonder if this is still up in
the air a bit. However I would be happy work on this, once I feel like I
understand what the consensus is for lexicals ...

--
Jonathan Sillito



Re: Lexical variables, scratchpads, closures, ...

2002-07-31 Thread Jonathan Sillito

On Wed, 2002-07-31 at 10:25, Jerome Vouillon wrote:
 
 Let us think a bit about the implementation of lexical variables.

Thanks for spelling this out in such detail. 

Here is a variation based on the lexical ops (new_pad, pop_pad,
store_lex, find_lex) committed yesterday. Note that lexical pads are
stored in the Parrot_Context struct's pad_stack field (see
include/parrot/interpreter.h).

In what follows I assume that all lexicals are stored as pointers
(instance of classes/pointer.pmc?) in the pad and that each scope will
have a reference to all of the pointers it needs to know about. In other
words a each pad has a pointer to all lexical variables declared or
referenced in the scope associated with the pad. A given pointer object
may live in multiple pads.

So:

- store_lex does not change the object that is in the hash, it just
changes what the object points to,

- and find_lex does not return the (pointer) object in the hash, it
returns the object pointed to by the object in the hash.

So here is my take on a slightly simpler example:

  sub foo {
my $x = 13;
return sub { print $x\n; };
  }

  $foo()

  main:

new_pad   # push this on the lexical stack
  # some constant descriptor should also be passed
  # to the new_pad op which would then know about
  # the lexical variable 'x', and would create an
  # associated pointer object

new P0, .Sub # gets current lexicals from interp's context
set_addr I0, foo
set P0, I0 # current hack to get the correct address in sub
pop_pad

invoke# assumes sub is in P0
  # on invoke the sub pmc fixes the current
  # context to have the correct lexicals
end

  foo:  # We assume the closure is in P0

new P1, .Int
store_lex P1, x   # probably by number not by name but ...
  # the store would then store the new int in a
  # the pointer object already allocated
  
set P1, 13
   
new_pad   # again a constant descriptor should be passed
  # to the new_pad op which would then know about
  # the lexical variable 'x', and would get a pointer
  # object from the parent scope (ie would not 
  # allocated a new pointer)

new P0, .Sub # this would then get the correct lexical
  # info from interp's context so no need for a 
  # set_pad op
set_addr I0, sub
set P0, I0 # current hack to get the correct address in sub
pop_pad

ret # return the sub object

  sub:
# on invoke the correct lexicals are in the current scope
find_lex P1, x  # again probably by index not name
  # after this P1 holds the int pmc
# print 
ret

Does that make sense?
--
Jonathan Sillito





Re: Lexical variables, scratchpads, closures, ...

2002-07-31 Thread Jonathan Sillito

On Wed, 2002-07-31 at 13:49, Jerome Vouillon wrote:
 On Wed, Jul 31, 2002 at 11:40:39AM -0600, Jonathan Sillito wrote:
  new_pad   # push this on the lexical stack
# some constant descriptor should also be passed
# to the new_pad op which would then know about
# the lexical variable 'x', and would create an
# associated pointer object
 
 Do you really need a stack?

A stack is how it is currently implemented. As Melvin suggested, this
makes it easy to push an pop scopes as each block is entered and exited.
There is an example of this in examples/assembly/lexicals.pasm

Of course other approaches's are possible.

 When is the pointer object created?

This part is not implemented currently. Once there is a pad descriptor
that the assembler understands, the pointer object could be created
immediately (maybe pointing to an instance of the PerlUndef pmc?).

BTW: is anyone working on or thinking about pad descriptors right now?

 
  invoke# assumes sub is in P0
# on invoke the sub pmc fixes the current
# context to have the correct lexicals
 
 Can you elaborate on this?  What is done precisely to fix the current
 context?

This also is not implemented (unless Sean O'Rourke's recent patch does
this?) However the Sub (or Coroutine, or Continuation, or ...) PMC could
have the responsibility of putting the correct context in place before
actually jumping to the body of the sub. Melvin's code in sub.c has a
start on this, I think ... 

I am kind of just thinking out loud here, but does that clear up
anything?
--
Jonathan Sillito



Re: [perl #15800] [PATCH] lexical scope ops, test and example

2002-07-30 Thread Jonathan Sillito

On Mon, 2002-07-29 at 17:12, Simon Glover wrote:
  I think you forgot to attach the patch...

oops, now the files are attached ...
 - patch: lex.patch
 - test file: lexicals.t
 - example file: lexicals.pasm

On Tue, 2002-07-30 at 02:14, Stephen Rawls wrote:
 --- Jonathan Sillito 
  close_lex # end of nested lexical scope
  
find_lex P3, a
print P3 # prints 12
print \n
end
  
 
 That's a typo, right?  It should print the first value
 of a (10).  Just making sure I'm not crazy ...

Hey, thanks for reading this over. It is not a typo, but it may be
incorrect. My code does overwrite previous lexicals in enclosing scopes
(i.e. lexicals in pads lower on the stack), but maybe I have the
semantics of the store_lex op wrong? The following example shows what I
had in mind:

  my $x = 13;

  sub foo 
  {
$x = 12;
  }

  foo();
  print $x; # prints 12

The alternative (what you have in mind I guess) is:

  my $x = 13;

  sub foo 
  {
 my $x = 12; # notice the my
  }

  foo();
  print $x; # prints 13

So I guess I see your point. Let me know if I should change the
implementation (it would be a quick change). Also note that there is
currently no support for accessing lexicals by index or for creating
pads from descriptors.

Thanks for any comments.
--
Jonathan Sillito



Index: core.ops
===
RCS file: /cvs/public/parrot/core.ops,v
retrieving revision 1.187
diff -u -r1.187 core.ops
--- core.ops	26 Jul 2002 19:15:56 -	1.187
+++ core.ops	29 Jul 2002 23:03:24 -
 -3604,6 +3604,24 
 
 
 
+=item Bopen_lex()
+
+Start a new lexical scope
+
+=item Bclose_lex()
+
+Close most recently opened lexical scope
+
+=item Bstore_lex(in PMC, in STR)
+
+Store object $1 as lexical symbol $2. This currently involves
+looking back through the stack of pads to see if there is an
+entry (corresponding to $2) that should be overwritten.
+
+=item Bfind_lex(in PMC, in STR)
+
+Find the lexical variable named $2 and store it in $1
+
 =item Bstore_global(in PMC, in STR)
 
 Store global $1 as global symbol $2
 -3613,6 +3631,80 
 Find the global named $2 and store it in $1
 
 =cut
+
+op open_lex() {
+PMC* hash = pmc_new(interpreter, enum_class_PerlHash);
+stack_push(interpreter, interpreter-ctx.pad_stack, hash, STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
+
+goto NEXT();
+}
+
+op close_lex() {
+stack_pop(interpreter, interpreter-ctx.pad_stack, NULL, STACK_ENTRY_DESTINATION);
+goto NEXT();
+}
+
+op store_lex(in PMC, in STR) {
+Stack_Chunk_t *cur_stack;
+Stack_Entry_t *entry = NULL;
+PMC * cur_hash = NULL;
+PMC * found = NULL;
+unsigned int i;
+KEY key;
+Stack_entry_type type = 0;
+
+MAKE_KEY(key, $2, enum_key_string, struct_val);
+
+/* walk back through stack of pads for the key */
+cur_stack = interpreter-ctx.pad_stack;
+while (cur_stack) {
+if (cur_stack-buffer) { 
+entry = (Stack_Entry_t *)(cur_stack-buffer-bufstart);
+for (i = 0; i  cur_stack-used; i++) {
+   cur_hash = (PMC *)entry[i].entry.pmc_val;
+   found = cur_hash-vtable-get_pmc_keyed(interpreter, cur_hash, key);
+   if (found) break;
+}
+}
+cur_stack = cur_stack-prev;
+}
+
+if (!found) { /* set the top pad to be cur_hash */
+	cur_hash = (PMC *)stack_peek(interpreter, interpreter-ctx.pad_stack, type);
+}
+cur_hash-vtable-set_pmc_keyed(interpreter, cur_hash, NULL, $1, key);
+   
+goto NEXT();
+}
+
+op find_lex(out PMC, in STR) {
+Stack_Chunk_t *cur_stack;
+Stack_Entry_t *entry = NULL;
+PMC * cur_hash = NULL;
+PMC * found = NULL;
+unsigned int i;
+KEY key;
+
+MAKE_KEY(key, $2, enum_key_string, struct_val);
+
+cur_stack = interpreter-ctx.pad_stack;
+while (cur_stack) {
+if (cur_stack-buffer) { 
+entry = (Stack_Entry_t *)(cur_stack-buffer-bufstart);
+for (i = 0; i  cur_stack-used; i++) {
+   cur_hash = (PMC *)entry[i].entry.pmc_val;
+   found = cur_hash-vtable-get_pmc_keyed(interpreter, cur_hash, key);
+   if (found) break;
+}
+}
+cur_stack = cur_stack-prev;
+}
+
+/* found will still be NULL if key was not found 
+ * FIXME: should the not found case be an internal_exception ? */
+$1 = found;
+goto NEXT();
+}
 
 op store_global(in PMC, in STR) {
 KEY key;
Index: dod.c
===
RCS file: /cvs/public/parrot/dod.c,v
retrieving revision 1.8
diff -u -r1.8 dod.c
--- dod.c	23 Jul 2002 07:25:02 -	1.8
+++ dod.c	29 Jul 2002 23:03:24 -
 -92,6 +92,23 
 }
 }
 
+/* Walk lexical pad stack */
+cur_stack = interpreter-ctx.pad_stack;
+while (cur_stack) {
+if (cur_stack-buffer) {
+	buffer_lives(cur_stack-buffer);
+	entry = (Stack_Entry_t

Re: [perl #15800] [PATCH] lexical scope ops, test and example

2002-07-30 Thread Jonathan Sillito

Thanks for the correction. May I ask about the find_lex op? In my
implementation it looks back through the stack of pads for the given
lexical:

 new P0, .PerlInt
 new P1, .PerlInt
 set P0, 10

  open_lex
  store_lex P0, a

# nested lexical scope
open_lex
find_lex P1, a
print P1 # prints 10

# etc

Also, should open_lex/close_lex be named new_pad/close_pad instead?

If you want to hold off on applying the patch, I will submit one with
the correct semantics in the next couple of hours. Or if you have
already submitted it I will send a patch to fix it.

Thanks again.
--
Jonathan Sillito

On Tue, 2002-07-30 at 10:47, Melvin Smith wrote:
 See my 2 comments:
 
   new P0, .PerlInt
   new P1, .PerlInt
   new P2, .PerlInt
   new P3, .PerlInt
   set P0, 10
   set P1, 11
   set P2, 12
 
   # outer most lexical scope
   open_lex
 New pad
   store_lex P0, a
   find_lex P3, a
   print P3 # prints 10
   print \n
 
 # nested lexical scope
 open_lex
 store_lex P1, b
 find_lex P3, b
 print P3 # prints 11
 print \n
 
 store_lex P2, a # overwrites previous a
  ^ Should not overwrite, should shadow since it is
 stored
in the current pad
 find_lex P3, a
 print P3 # prints 12
 print \n
 
 close_lex # end of nested lexical scope
  ^ Pad goes away, with b and a, so the outer values
should be back in effect.
 
   find_lex P3, a
   print P3 # prints 12
   print \n
   end
 
 I'll apply this, since it is clean, but the semantics need adjustment.
 Thanks,
 
 -Melvin Smith
 
 IBM :: Atlanta Innovation Center
 [EMAIL PROTECTED] :: 770-835-6984
 




Re: lexical scopes and scratchpads

2002-07-24 Thread Jonathan Sillito

Thanks for the response.

On Tue, 2002-07-23 at 13:23, Melvin Smith wrote:
[reordered]

 If you want to take a whack at it before I get to it, take a look at the
 global variable ops, although they aren't perfect. I just stacked them
 on top of the Hash PMC that we already had.

If you think you won't get to it for a while then I would be happy to
give it a stab.

 I started on a simple implementation. I decided to just use the
 PerlHash that we already have.
 
 I planned to add a new stack for lexical scopes, making it COW,
 and the newpad op would simply create a new Hash PMC and push
 it onto that stack, and vice-versa.

[...]

 The fun part after you get the skeleton working is copying the
 pads on write for closures, etc.

Do you think a linked list approach (like 'struct Stash' for globals)
where each scope has a link to it's parent scope would be both simpler
and sufficient?

We could give the Parrot_Context struct a pointer to the current scope,
and inside of the invoke method of the Closure (Sub?) PMC I think we
would just need to set the interpreter's pointer to the correct scope,
something like:

  interpreter-ctx.current_scope = SELF-scope;

What do you think? Is there something I am misunderstanding about how
closures work?

 On this line, we need to discuss the symbol table format for
 the bytecode. I played around a bit but nothing I wish to commit.

I haven't given this any thought yet ...

--
Jonathan Sillito




lexical scopes and scratchpads

2002-07-23 Thread Jonathan Sillito

Is now a good time to start a discussion on lexical scopes? Is anyone
currently working on an implementation of scratchpads? I have sketched
out a simple implementation, based on the struct at the end of this
email, but there are somethings that I do not understand, so I am hoping
someone can set me straight. Here are my two main questions:

1) How should a scratchpad be created. The only documentation I found
was in docs/parrot_assembly.pod:

Pad descriptors are templates for a particular pad. They are specified
in the constant area of a bytecode file, and contain the names, types,
and attributes for the variables referenced in the scope the pad is for.
[...]
newpad pad_descriptor
   Create a new scratchpad using pad_descriptor as a template.

Has anyone worked out how pad descriptors will look and be handled by
the assembler, passed to constructor, etc?

2) How are values stored in scratchpads? Will scratchpads only contain
pointers?

/* Scratchpad, for implementing lexically scoped variables. */
typedef struct Scratchpad {
/* sub class of buffer (?) */
Buffer buffer;

/* pad for enclosing lexical scope */
struct Scratchpad *parent;

/* for (slow) by name access, this could be a string
   to int hash instead */
struct parrot_string_t * names;

/* for (faster) by index access */
PMC * data;

/* subtracted from indexes before accessing data,
   calculated from the parent's offset and size
   (an index less than this offset, should refer to
   a variable in an enclosing scope) */
INTVAL offset;

/* number of pointers in data */  
INTVAL size;
} * scratchpad_t;


Thanks, for any help/feedback!
--
Jonathan Sillito



[PATCH] add invoke vtable method

2002-07-22 Thread Jonathan Sillito

On Fri, 2002-07-19 at 16:36, Melvin Smith wrote:
 Send me a complete patch and I'll put it in. I might rename the
 op to 'call'.

The attached patch makes the following changes:

- adds invoke op to core.ops (patch does not remove call and callco)
- adds vtable method 'invoke' to vtable.tbl
- adds simple description (stolen from Dan's email) of the method to
docs/pdd/pdd02_vtables.pod
- adds default invoke to classes/default.pmc
- adds an invoke method to classes/sub.pmc
- adds an invoke method to classes/coroutine.pmc

If either the op or the vtable method (or both) should be be named
'call' instead of 'invoke' then let me know and I will rework my stuff
and resubmit the patch.

I had a small patch ready for docs/core_ops.pod, but I see that the file
has been removed, so now I am not sure where to put the description of
the invoke op. 

Next on my list is (next 24 hours or so):

1) remove old call and callco ops (invoke takes care of both) from
core.ops
2) change examples/assembly/sub.pasm and coroutine.pasm to use invoke
instead of call and callco
3) add some tests

After that I will look into adding a Continuation PMC.

--
Jonathan Sillito



Index: core.ops
===
RCS file: /cvs/public/parrot/core.ops,v
retrieving revision 1.185
diff -u -r1.185 core.ops
--- core.ops	18 Jul 2002 04:29:39 -	1.185
+++ core.ops	22 Jul 2002 16:52:05 -
 -4179,6 +4179,34 
   goto NEXT();
 }
 
+inline op invoke() {
+  opcode_t *dest;
+  PMC * p = interpreter-ctx.pmc_reg.registers[0];
+
+  /*
+   * FIXME: the stack manipulation code (this push and the pop below) should
+   * be moved to the vtable method. (I think ?)
+   */
+  stack_push(interpreter, interpreter-ctx.control_stack, expr NEXT(), STACK_ENTRY_DESTINATION, STACK_CLEANUP_NULL);
+
+  dest = (opcode_t *)p-vtable-invoke(interpreter, p);
+  if(dest == 0) {
+/*
+ * invoke returned 0 (means nothing more needs to be done), so just
+ * move on to the next instruction
+ */
+stack_pop(interpreter, interpreter-ctx.control_stack, NULL, STACK_ENTRY_DESTINATION);
+goto NEXT();
+  }
+  else {
+/* 
+ * invoke returned non 0, so it should have returned a and address
+ * so that's our next
+ */
+goto ADDRESS(dest);
+  }
+}
+
 inline op call() {
   /* This op will be a vtable entry */
   struct Parrot_Sub * sub = (struct Parrot_Sub*)interpreter-ctx.pmc_reg..registers[0]-data;
Index: vtable.tbl
===
RCS file: /cvs/public/parrot/vtable.tbl,v
retrieving revision 1.25
diff -u -r1.25 vtable.tbl
--- vtable.tbl	21 Jun 2002 17:22:01 -	1.25
+++ vtable.tbl	22 Jul 2002 16:52:05 -
 -325,3 +325,5 
 STRING* substr_str(INTVAL offset, INTVAL length)
 STRING* substr_str_keyed(KEY* key, INTVAL offset, INTVAL length)
 STRING* substr_str_keyed_int(INTVAL* key, INTVAL offset, INTVAL length)
+
+INTVAL invoke()
Index: docs/pdds/pdd02_vtables.pod
===
RCS file: /cvs/public/parrot/docs/pdds/pdd02_vtables.pod,v
retrieving revision 1.19
diff -u -r1.19 pdd02_vtables.pod
--- docs/pdds/pdd02_vtables.pod	21 Jun 2002 17:23:37 -	1.19
+++ docs/pdds/pdd02_vtables.pod	22 Jul 2002 16:52:05 -
 -1194,6 +1194,18 
 
 The key is guaranteed to be not NULL.
 
+=item INTVAL invoke(INTERP, PMC* self)
+
+For invoking Invoke the given PMC. 
+
+It should set up the environment for the sub and return the absolute
+address that the interpreter should jump to. If it returns 0, then 
+the interpreter should just take up with the next instruction. (If the 
+sub just goes and does its thing and returns, which most C subs will 
+do at the moment) 
+
+See pdd03_calling_conventions.pod for more details.
+
 =back
 
 =cut
Index: classes/default.pmc
===
RCS file: /cvs/public/parrot/classes/default.pmc,v
retrieving revision 1.24
diff -u -r1.24 default.pmc
--- classes/default.pmc	18 Jul 2002 02:19:16 -	1.24
+++ classes/default.pmc	22 Jul 2002 16:52:06 -
 -2478,4 +2478,15 
 INT_TO_KEY(r_key, *key);
 return SELF-vtable-substr_str_keyed(INTERP, SELF, r_key, offset, length);
 }
+
+INTVAL invoke() {
+	/* 
+ * FIXME: should be an exception instead: 
+ * Invoking something that can not be invoked ??
+ */
+
+/* returning 0 should mean the interpretor will move on to the next op */
+return 0;
+
+}
 }
Index: classes/sub.pmc
===
RCS file: /cvs/public/parrot/classes/sub.pmc,v
retrieving revision 1.2
diff -u -r1.2 sub.pmc
--- classes/sub.pmc	18 Jul 2002 03:48:33 -	1.2
+++ classes/sub.pmc	22 Jul 2002 16:52:06 -
 -325,4 +325,9 
void repeat_same (PMC * value, PMC* dest) {
}
 */
+
+   INTVAL invoke () {
+ /* return address that the interpreter should jump to */
+ return ((struct

Re: Subs?

2002-07-18 Thread Jonathan Sillito

On Wed, 2002-07-17 at 22:01, Melvin Smith wrote:
 Subs, co-routines and continuations are at a very limited, but functional
 state.
 
 Basically you can create a PMC with a bytecode address or label
 and use the call/callco/callcc ops on it.


Subs seem to be broken right now. Here is a pasm file

  set_addr I0, MYSUB
  new P0, .Sub, I0
  call
  end

  MYSUB:
  print this is the sub\n
  ret

and the output from running the associated pbc file

   ./parrot rough.pbc
  Segmentation fault

   ./parrot -t rough.pbc
  PC=0; OP=65 (set_addr_i_ic); ARGS=(I0=0, 9)
  PC=3; OP=727 (new_p_ic_i); ARGS=(P0=0x81403c0, 9, I0=135578484)
  PC=7; OP=757 (call)

If I understand things correctly, the problem is that the address
argument (i.e. the last argument) to the new op is being ignored, and
sub-init is always set to 0. So the call op is returning 0 as the next
op for the interpreter (in core.ops):

  goto ADDRESS(sub-init); /* always 0 */

Is there a different pasm syntax I should be using for creating and
calling subs? I seem to remember some discussion about changing how
things are passed to constructors but I am not sure what the conclusion
was.

--
Jonathan Sillito




Re: [PATCH] Subs?

2002-07-18 Thread Jonathan Sillito

On Thu, 2002-07-18 at 14:27, Melvin Smith wrote:
 The temporary fix is to do:
 
 new P0, .Sub
 set_addr I0, MYSUB
 set P0, I0
 call

Attached are three small patches, two of them change example files
(examples/assembly/coroutine.pasm and examples/assembly/sub.pasm)
to use this fix that Melvin mentioned.

The third is a fix for a simple bug in coroutine.pmc: Parrot_Coroutine
was being cast to a Parrot_Sub which caused a seg fault when callco was
called.

(This is my first attempt at sending patches to the list, so any
comments about how this should really be done would be appreciated.)

--
Jonathan Sillito


Index: examples/assembly/sub.pasm
===
RCS file: /cvs/public/parrot/examples/assembly/sub.pasm,v
retrieving revision 1.2
diff -u -r1.2 sub.pasm
--- examples/assembly/sub.pasm	7 Jun 2002 23:41:21 -	1.2
+++ examples/assembly/sub.pasm	18 Jul 2002 22:51:09 -
 -1,13 +1,20 
+# sub.pasm
+#
 # Sample sub-routines in Parrot
 #
-# Create 2 subroutines
+# $Id: $
 #
-set_addr I0, SUB 
-new P0, .ParrotSub, I0 
+
+# Create 2 subroutines
+set_addr I0, SUB
+new P0, .Sub
+set P0, I0
 save P0
-new P0, .ParrotSub, I0 
+new P0, .Sub
+set P0, I0
 # Calling convention says P0 will contain the sub
 call
+
 restore P0
 # Call second one
 call


Index: classes/coroutine.pmc
===
RCS file: /cvs/public/parrot/classes/coroutine.pmc,v
retrieving revision 1.2
diff -u -r1.2 coroutine.pmc
--- classes/coroutine.pmc	18 Jul 2002 03:48:33 -	1.2
+++ classes/coroutine.pmc	18 Jul 2002 22:53:12 -
 -77,11 +77,11 
}
 */
void set_integer (PMC * value) {
-   ((struct Parrot_Sub*)SELF-data)-init = (opcode_t*)value-vtable-get_integer(INTERP, value);
+   ((struct Parrot_Coroutine*)SELF-data)-init = (opcode_t*)value-vtable-get_integer(INTERP, value);
}
 
void set_integer_native (INTVAL value) {
-   ((struct Parrot_Sub*)SELF-data)-init = (opcode_t*)value;
+   ((struct Parrot_Coroutine*)SELF-data)-init = (opcode_t*)value;
}
 /*
void set_integer_bigint (BIGINT value) {


Index: examples/assembly/coroutine.pasm
===
RCS file: /cvs/public/parrot/examples/assembly/coroutine.pasm,v
retrieving revision 1.1
diff -u -r1.1 coroutine.pasm
--- examples/assembly/coroutine.pasm	7 Jun 2002 23:36:03 -	1.1
+++ examples/assembly/coroutine.pasm	18 Jul 2002 22:50:56 -
 -1,11 +1,17 
+# coroutine.pasm
+# 
 # Sample co-routines in Parrot
 #
-# Create 2 coroutines
+# $Id: $
 #
+
 set_addr I0, MYCOROUTINE 
-new P0, .ParrotCoroutine, I0 
+new P0, .Coroutine
+set P0, I0
 save P0
-new P0, .ParrotCoroutine, I0 
+new P0, .Coroutine
+set P0, I0
+
 # Calling convention says P0 will contain the sub so..
 print Calling 1st co-routine\n
 callco