cvsuser     02/11/14 21:49:07

  Modified:    .        MANIFEST core.ops sub.c
  Log:
  Jonathan Sillito:
  
  The attached patch implements a very complete set of lexical scope
  semantics. For those that have been following along, here are some
  highlights.
  
  - supports (fast) access by lexical position, rather than just by name
  
  - adds a couple more ops and some variations, including push_pad and
  peek_pad
  
  - adds a couple of keyed vtable functions for Scratchpad PMCs, so the
  following work in a similar way to the various flavours of find_lex and
  store_lex. The difference is that the find_lex and store_lex ops work
  implicitly on the current pad, while these let you explicitly specify a pad
  
     new_pad P20, 0        # does not push on stack
     set P20[0;"foo"], P0  # like: store_lex Ix, Sy, Pz
     set P20[0;0], P0      # like: store_lex Ix, Iy, Pz
     set P20["foo"], P0    # like: store_lex Sx, Py
     set P20[0], P0        # like: store_lex Ix, Py
     set P3, P20[0;"foo"]  # like: find_lex Px, Iy, Sz
     set P3, P20[0;0]      # like: find_lex Px, Iy, Iz
     set P4, P20["foo"]    # like: find_lex Px, Sy
     set P4, P20[0]        # like: find_lex Px, Iy
  
  - not based on PerlHash
  
  Revision  Changes    Path
  1.251     +2 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.250
  retrieving revision 1.251
  diff -u -w -r1.250 -r1.251
  --- MANIFEST  14 Nov 2002 05:33:01 -0000      1.250
  +++ MANIFEST  15 Nov 2002 05:49:06 -0000      1.251
  @@ -36,6 +36,7 @@
   classes/pmc2c.pl
   classes/pointer.pmc
   classes/scalar.pmc
  +classes/scratchpad.pmc
   classes/sub.pmc
   config/auto/alignptrs.pl
   config/auto/alignptrs/test_c.in
  @@ -1627,6 +1628,7 @@
   t/pmc/perlint.t
   t/pmc/perlstring.t
   t/pmc/pmc.t
  +t/pmc/scratchpad.t
   t/pmc/sub.t
   t/src/basic.t
   t/src/exit.t
  
  
  
  1.228     +117 -20   parrot/core.ops
  
  Index: core.ops
  ===================================================================
  RCS file: /cvs/public/parrot/core.ops,v
  retrieving revision 1.227
  retrieving revision 1.228
  diff -u -w -r1.227 -r1.228
  --- core.ops  8 Nov 2002 05:18:39 -0000       1.227
  +++ core.ops  15 Nov 2002 05:49:06 -0000      1.228
  @@ -3643,22 +3643,68 @@
   
   ########################################
   
  -=item B<new_pad>()
  +=item B<new_pad>(in INT)
   
  -Create a new lexical scope pad and push it onto the
  -current lexical scope stack.
  +Create a new lexical scope pad with static nesting depth $1
  +and push it onto the lexical scope stack. Static depths 0 
  +through $1 - 1, inclusive, are copied from the current static 
  +nesting.
  +
  +=item B<new_pad>(out PMC, in INT)
  +
  +Create a new lexical scope pad with static nesting depth $2
  +and store it in $1 (do NOT push on the stack). Static depths 0 
  +through $2 - 1, inclusive, are copied from the current static 
  +nesting.
   
   =item B<pop_pad>()
   
   Pop the current lexical scope pad off the stack
   
  +=item B<pop_pad>(out PMC)
  +
  +Pop the current lexical scope pad off the stack and store
  +it in $1 (XXX JPS: not implemented yet).
  +
  +=item B<peek_pad>(out PMC)
  +
  +Store the current lexical scope pad (i.e. the one at the
  +top of the lexical pad stack) in $1.
  +
   =item B<store_lex>(in STR, in PMC)
   
  -Store object $2 as lexical symbol $1
  +Store object $2 as lexical symbol $1.  $1 must have already been
  +created at some static depth. 
  +
  +=item B<store_lex>(in INT, in STR, in PMC)
  +
  +Store object $3 as lexical $2 at depth $1.  If [$1, $2] does not
  +exist, it will be created.  If $1 is negative, count out from the
  +current lexical scope; otherwise, count in from the outermost scope.
  +So store_lex -1, .... will operate on the current pad.
  +
  +=item B<store_lex>(in INT, in INT, in PMC)
  +
  +Store object $3 at lexical position $2 at depth $1.  If [$1, $2] does 
  +not exist, it will be created.  If $1 is negative, count out from the
  +current lexical scope; otherwise, count in from the outermost scope.
  +So store_lex -1, .... will operate on the current pad.
   
   =item B<find_lex>(out PMC, in STR)
   
  -Find the lexical variable named $2 and store it in $1
  +Find the lexical variable named $2 (at any depth) and store it in $1.
  +
  +=item B<find_lex>(out PMC, in INT, in STR)
  +
  +Find the lexical variable named $3 at depth $2 and store it in $1. 
  +If $2 is negative the, count out from the current lexical scope; 
  +otherwise, count up from the outermost scope.
  +
  +=item B<find_lex>(out PMC, in INT, in INT)
  +
  +Find the lexical variable at position $3 at depth $2 and store it in
  +$1. If $2 is negative the, count out from the current lexical scope; 
  +otherwise, count up from the outermost scope.
   
   =item B<store_global>(in STR, in PMC)
   
  @@ -3670,36 +3716,87 @@
   
   =cut
   
  -op new_pad() {
  -    PMC* hash = pmc_new(interpreter, enum_class_PerlHash);
  -    stack_push(interpreter, &interpreter->ctx.pad_stack, hash, STACK_ENTRY_PMC, 
STACK_CLEANUP_NULL);
  +op new_pad(in INT) {
  +    PMC * pad;
  +    PMC * parent = (PMC *)stack_peek(interpreter,
  +                                  interpreter->ctx.pad_stack, NULL);
  +    pad = scratchpad_new(interpreter, parent, $1);
  +    stack_push(interpreter, &interpreter->ctx.pad_stack, pad,
  +               STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
  +    goto NEXT();
  +}
  +
  +op new_pad(out PMC, in INT) {
  +    PMC * parent = (PMC *)stack_peek(interpreter, 
  +                                     interpreter->ctx.pad_stack, NULL);
  +    $1 = scratchpad_new(interpreter, parent, $2);
  +    goto NEXT();
  +}
   
  +op push_pad(in PMC) {
  +    stack_push(interpreter, &interpreter->ctx.pad_stack, $1,
  +               STACK_ENTRY_PMC, STACK_CLEANUP_NULL);
       goto NEXT();
   }
   
   op pop_pad() {
  -    stack_pop(interpreter, &interpreter->ctx.pad_stack, NULL, STACK_ENTRY_PMC);
  +    stack_pop(interpreter, &interpreter->ctx.pad_stack, 
  +              NULL, STACK_ENTRY_PMC);
  +    goto NEXT();
  +}
  +
  +op peek_pad(out PMC) {
  +    $1 = (PMC*)stack_peek(interpreter, 
  +                          interpreter->ctx.pad_stack, NULL);
       goto NEXT();
   }
   
   op store_lex(in STR, in PMC) {
  -    PMC * hash = NULL;
  -    PMC * key = key_new_string(interpreter, $1);
  -    Stack_entry_type type = NO_STACK_ENTRY_TYPE;
  -    hash = (PMC *)stack_peek(interpreter, interpreter->ctx.pad_stack, &type);
  -    hash->vtable->set_pmc_keyed(interpreter, hash, key, $2, NULL);
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                                  interpreter->ctx.pad_stack, NULL);
  +    scratchpad_store(interpreter, pad, $1, 0, $2);
  +    goto NEXT();
  +}
  +
  +op store_lex(in INT, in STR, in PMC) {
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                                  interpreter->ctx.pad_stack, NULL);
  +    scratchpad_store_index(interpreter, pad, $1, $2, 0, $3);
  +    goto NEXT();
  +}
  +
  +op store_lex(in INT, in INT, in PMC) {
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                                  interpreter->ctx.pad_stack, NULL);
  +    scratchpad_store_index(interpreter, pad, $1, NULL, $2, $3);
       goto NEXT();
   }
   
   op find_lex(out PMC, in STR) {
  -    PMC * hash = NULL;
  -    PMC * key = key_new_string(interpreter, $2);
  -    Stack_entry_type type = NO_STACK_ENTRY_TYPE;
  -    hash = (PMC *)stack_peek(interpreter, interpreter->ctx.pad_stack, &type);
  -    $1 = hash->vtable->get_pmc_keyed(interpreter, hash, key);
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                               interpreter->ctx.pad_stack, NULL);
  +    $1 = scratchpad_get(interpreter, pad, $2, 0);
  +    goto NEXT();
  +}
   
  -    /* FIXME: should the not found case be an internal_exception ? */
  +op find_lex(out PMC, in INT) {
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                               interpreter->ctx.pad_stack, NULL);
  +    $1 = scratchpad_get(interpreter, pad, NULL, $2);
  +    goto NEXT();
  +}
  +
  +op find_lex(out PMC, in INT, in STR) {
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                               interpreter->ctx.pad_stack, NULL);
  +    $1 = scratchpad_get_index(interpreter, pad, $2, $3, 0);
  +    goto NEXT();
  +}
   
  +op find_lex(out PMC, in INT, in INT) {
  +    PMC * pad = (PMC *)stack_peek(interpreter,
  +                               interpreter->ctx.pad_stack, NULL);
  +    $1 = scratchpad_get_index(interpreter, pad, $2, NULL, $3);
       goto NEXT();
   }
   
  
  
  
  1.9       +194 -2    parrot/sub.c
  
  Index: sub.c
  ===================================================================
  RCS file: /cvs/public/parrot/sub.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -w -r1.8 -r1.9
  --- sub.c     2 Nov 2002 14:57:47 -0000       1.8
  +++ sub.c     15 Nov 2002 05:49:06 -0000      1.9
  @@ -1,7 +1,7 @@
   /*  sub.c
    *  Copyright: (When this is determined...it will go here)
    *  CVS Info
  - *     $Id: sub.c,v 1.8 2002/11/02 14:57:47 josh Exp $
  + *     $Id: sub.c,v 1.9 2002/11/15 05:49:06 sfink Exp $
    *  Overview:
    *     Sub-routines, co-routines and other fun stuff...
    *  Data Structure and Algorithms:
  @@ -64,6 +64,198 @@
   }
   
   /*
  + * Uses scope_index to find and return the appropriate scope.
  + */
  +static struct Parrot_Lexicals *
  +scratchpad_index(struct Parrot_Interp* interpreter, PMC* pad, 
  +                 INTVAL scope_index)
  +{
  +    /* if scope_index is negative we count out from current pad */
  +    scope_index = scope_index < 0 ? 
  +        pad->cache.int_val + scope_index : scope_index;
  +
  +    if (scope_index >= pad->cache.int_val || scope_index < 0) {
  +        internal_exception(-1, "Pad index out of range");
  +        return NULL;
  +    }
  +
  +    return ((struct Parrot_Lexicals **)pad->data)[scope_index];
  +}
  +
  +/* 
  + * Returns the position of the lexical variable corresponding to
  + * name. If such a variable can not be found the length of the list
  + * is returned (i.e. the position that this new lexical should be
  + * stored in).
  + */
  +static INTVAL
  +lexicals_get_position(struct Parrot_Interp * interp, 
  +                      struct Parrot_Lexicals *lex, STRING* name)
  +{
  +    STRING * cur;
  +    INTVAL pos;
  +
  +    for (pos = 0; pos < list_length(interp, lex->names); pos++) {
  +        cur = *(STRING**)list_get(interp, lex->names, pos, enum_type_STRING);
  +        if (cur && string_compare(interp, cur, name) == 0) {
  +            break;
  +        }
  +    }
  +
  +    return pos;
  +}
  +
  +/*
  + * Returns first lexical scope and position where name is found, or
  + * NULL if it can not be found.
  + */
  +static struct Parrot_Lexicals *
  +scratchpad_find(struct Parrot_Interp* interp, PMC* pad, STRING * name,
  +                INTVAL * position)
  +{
  +    INTVAL i, pos = 0;
  +    struct Parrot_Lexicals * lex = NULL;
  +
  +    for (i = pad->cache.int_val - 1; i >= 0; i--) {
  +        lex = ((struct Parrot_Lexicals **)pad->data)[i];
  +        pos = lexicals_get_position(interp, lex, name);
  +        if (pos == list_length(interp, lex->names))
  +            lex = NULL;
  +        else
  +            break;
  +    }
  +
  +    *position = pos;
  +    return lex;
  +}
  +
  +/*
  + * Creates and initializes a new Scratchpad PMC.
  + */
  +PMC*
  +scratchpad_new(struct Parrot_Interp * interp, PMC * base, INTVAL depth)
  +{
  +    struct Parrot_Lexicals * lex;
  +    PMC * pad_pmc = pmc_new(interp, enum_class_Scratchpad);
  +    pad_pmc->cache.int_val = 0;
  +
  +    if ((base && depth > base->cache.int_val) || (!base && depth != 0)) {
  +        internal_exception(-1, "-scratch_pad: too deep\n");
  +        return NULL;
  +    }
  +
  +    /* XXX JPS: should we use a List * here instead? */
  +    pad_pmc->data = mem_sys_allocate((depth + 1) * 
  +                                     sizeof(struct Parrot_Lexicals));
  +
  +    if (base) {
  +        memcpy(pad_pmc->data, base->data, depth * 
  +               sizeof(struct Parrot_Lexicals));
  +    }
  +
  +    lex = mem_sys_allocate(sizeof(struct Parrot_Lexicals));
  +    lex->values = list_new(interp, enum_type_PMC);
  +    lex->names = list_new(interp, enum_type_STRING);
  +
  +    ((struct Parrot_Lexicals **)pad_pmc->data)[depth] = lex;
  +    pad_pmc->cache.int_val = depth + 1;
  +    return pad_pmc;
  +}
  +
  +/*
  + * Routines for storing and reading lexicals in Scratchpad's. These
  + * take both a name and a position, however in general only one of
  + * these will be considered. This is to support both by name access
  + * and by position (which is faster). If by position access is intended
  + * name should be passed as NULL.
  + */
  +
  +void
  +scratchpad_store(struct Parrot_Interp * interp, PMC * pad, 
  +                 STRING * name, INTVAL position, PMC* value)
  +{
  +    INTVAL i;
  +    struct Parrot_Lexicals * lex;
  +
  +    if (name) { 
  +        /* use name to find lex and position */
  +        lex = scratchpad_find(interp, pad, name, &position);
  +        if (!lex) internal_exception(-1, "Lexical not found");
  +    }
  +    else { 
  +        /* assume current lexical pad */
  +        lex = scratchpad_index(interp, pad, -1);
  +    }
  +
  +    list_assign(interp, lex->values, position, value, enum_type_PMC);
  +}
  +
  +void 
  +scratchpad_store_index(struct Parrot_Interp * interp, PMC * pad, 
  +                       INTVAL scope_index, STRING * name, INTVAL position, 
  +                       PMC* value)
  +{
  +    INTVAL i;
  +    struct Parrot_Lexicals * lex;
  +
  +    lex = scratchpad_index(interp, pad, scope_index);
  +
  +    if (name) {
  +        position = lexicals_get_position(interp, lex, name);
  +    }
  +
  +    if (position == list_length(interp, lex->names)) {
  +        if (!name) {
  +            /* no name for new variable, give it a default name of "" */
  +            /* XXX JPS: is this the way to make an empty string? */
  +            name = string_make(interp, "", 9,0,0,0);
  +        }
  +        list_assign(interp, lex->names, position, name, enum_type_STRING);
  +    }
  +
  +    list_assign(interp, lex->values, position, value, enum_type_PMC);
  +}
  +
  +PMC * 
  +scratchpad_get(struct Parrot_Interp * interp, PMC * pad, STRING * name, 
  +               INTVAL position)
  +{
  +    INTVAL i;
  +    struct Parrot_Lexicals * lex = NULL;
  +
  +    if (name) lex = scratchpad_find(interp, pad, name, &position);
  +    else lex = scratchpad_index(interp, pad, -1);
  +
  +    if (!lex) internal_exception(-1, "Lexical not found");
  +
  +    return *(PMC **)list_get(interp, lex->values, position, enum_type_PMC);
  +}
  +
  +PMC * 
  +scratchpad_get_index(struct Parrot_Interp * interp, PMC * pad,
  +                     INTVAL scope_index, STRING * name, INTVAL position)
  +{
  +    struct Parrot_Lexicals * lex = scratchpad_index(interp, pad, scope_index);
  +    
  +    if (name) {
  +        position = lexicals_get_position(interp, lex, name);
  +    }
  +
  +    if (!lex || position < 0 || position >= list_length(interp, lex->values)) {
  +        internal_exception(-1, "Lexical not found");
  +    }
  +    
  +    return *(PMC **)list_get(interp, lex->values, position, enum_type_PMC);
  +}
  +
  +PMC * 
  +lexicals_mark(struct Parrot_Interp * interp, struct Parrot_Lexicals *lex, PMC * 
last)
  +{
  +    last = list_mark(interp, lex->names, last);
  +    return list_mark(interp, lex->values, last);
  +}
  +
  +/*
    * Local variables:
    * c-indentation-style: bsd
    * c-basic-offset: 4
  
  
  


Reply via email to