Changeset 6432

Show
Ignore:
Timestamp:
08/23/05 23:42:59 (3 years ago)
Author:
iblech
Message:

* Pugs.AST.Scope: Reorder the declarations of the various scope types -- SLet

and STemp do something to *existing* variables. Accidentally, this causes
temp.t to pass on normal Pugs!

* Pugs.Lexer, Pugs.Compile: Acommodate for that change.
* PIL2JS: temp! let!

  • PIL: All JS functions have a block_leave_hooks array now, containing native JS functions to be called at block exit.
  • PIL::PPad uses this variable to implement the (possible) variable restoration needed for temp and let.

* t/var/let.t, t/var/temp.t: Should "temp @array[$index]" work? I think so, but

Pugs doesn't even parse that. Added appropriate tests in a =pod block.
BTW, let.t passes 7/7, temp.t passes 22/22 (with TODO tests).

Files:
7 modified

Legend:

Unmodified
Added
Removed
  • perl5/PIL2JS/lib/PIL.pm

    r6425 r6432  
    115115  return sprintf <<EOF, $name, $restores, $lvalue ? "" : "new PIL2JS.Box.ReadOnly(", $lvalue ? "" : ")" } 
    116116var __returncc = args.pop(); 
     117var block_leave_hooks = []; 
    117118var %s = function (retval) { 
     119  for(var i = 0; i < block_leave_hooks.length; i++) { 
     120    block_leave_hooks[i](retval); 
     121  } 
     122 
    118123  PIL2JS_callchain.pop(); PIL2JS_subpads.pop(); 
    119124  %s; 
  • perl5/PIL2JS/lib/PIL/PPad.pm

    r6270 r6432  
    99 
    1010  die unless keys %$self == 3; 
    11   die unless $self->{pScope} eq "SMy"; 
     11  # A SOur should never reach use (SOurs are compiled into __init_ subs). 
     12  die if     $self->{pScope} eq "SOur"; 
    1213  die unless ref $self->{pSyms} eq "ARRAY"; 
    1314  die unless $self->{pStmts}->isa("PIL::PStmts"); 
    1415 
    15   if($PIL::IN_SUBLIKE) { 
     16  # Skip creating a new sub-pad if 
     17  #   a) we're in a subroutine (in this case, we use JS' lexicals) or 
     18  #   b) we're compiling a SLet, STemp, or SState (which all use an existing 
     19  #      variable). 
     20  if($PIL::IN_SUBLIKE or $self->{pScope} =~ /^(SLet|STemp|SState)$/) { 
    1621    return bless { 
    1722      pScope => $self->{pScope}, 
    18       pSyms  => [map {{ fixed => $_->[0], user => $_->[0] }} @{ $self->{pSyms} }], 
     23      pSyms  => [map {{ fixed => PIL::lookup_var($_->[0]), user => $_->[0] }} @{ $self->{pSyms} }], 
    1924      pStmts => $self->{pStmts}->fixup, 
    2025    } => "PIL::PPad"; 
     
    5257  return 
    5358    join("; ", map { 
    54       sprintf "%s%s = %s; pad[%s] = %s", 
    55         $PIL::IN_SUBLIKE ? "var " : "", 
     59      my ($jsname, $qname, $undef) = ( 
    5660        PIL::name_mangle($_->{fixed}), 
     61        PIL::doublequote($_->{user}), 
    5762        PIL::undef_of($_->{fixed}), 
    58         PIL::doublequote($_->{user}), 
    59         PIL::name_mangle($_->{fixed}); 
     63      ); 
     64 
     65      if($self->{pScope} eq "SMy") { 
     66        "$decl$jsname = $undef; pad[$qname] = $jsname"; 
     67      } elsif($self->{pScope} eq "STemp") { 
     68        PIL::fail("Can't use temp variable declarator outside a sub-scope!") 
     69          unless $PIL::IN_SUBLIKE; 
     70        <<EOF; 
     71(function () { 
     72  var backup = $jsname.FETCH(); 
     73  block_leave_hooks.push(function () { 
     74    $jsname.STORE(new PIL2JS.Box.Constant(backup)); 
     75  }); 
     76})() 
     77EOF 
     78      } elsif($self->{pScope} eq "SLet") { 
     79        PIL::fail("Can't use temp variable declarator outside a sub-scope!") 
     80          unless $PIL::IN_SUBLIKE; 
     81        <<EOF; 
     82(function () { 
     83  var backup = $jsname.FETCH(); 
     84  block_leave_hooks.push(function (retval) { 
     85    if(!PIL2JS.cps2normal( 
     86      _26main_3a_3aprefix_3a_3f.FETCH(), 
     87      [PIL2JS.Context.ItemAny, retval] 
     88    ).FETCH()) 
     89      $jsname.STORE(new PIL2JS.Box.Constant(backup)); 
     90  }); 
     91})() 
     92EOF 
     93      } else { 
     94        die; 
     95      } 
    6096    } @{ $self->{pSyms} }) . 
    6197    ";\n" . 
  • src/Pugs/AST/Scope.hs

    r5166 r6432  
    77-- | The scope of a variable declaration. 
    88data Scope = SState  -- ^ Persistent across calls 
     9           | SLet    -- ^ Hypotheticalised (reverted upon failure) 
     10           | STemp   -- ^ Temporary (reverted at scope exit) 
    911           | SMy     -- ^ Lexical 
    1012           | SOur    -- ^ Package 
    11            | SLet    -- ^ Hypotheticalised (reverted upon failure) 
    12            | STemp   -- ^ Temporary (reverted at scope exit) 
    1313           | SGlobal -- ^ Global 
    1414    deriving (Show, Eq, Ord, Enum) 
  • src/Pugs/Compile.hs

    r6424 r6432  
    142142    compile (Stmts (Pad SOur _ exp) rest) = do 
    143143        compile $ mergeStmts exp rest 
    144     compile (Stmts (Pad _ pad exp) rest) = do 
     144    compile (Stmts (Pad scope pad exp) rest) = do 
    145145        expC    <- compile $ mergeStmts exp rest 
    146146        padC    <- compile $ padToList pad 
    147         return $ PPad SMy ((map fst $ padToList pad) `zip` padC) expC 
     147        return $ PPad scope ((map fst $ padToList pad) `zip` padC) expC 
    148148    compile exp = compileStmts exp 
    149149 
  • src/Pugs/Lexer.hs

    r6393 r6432  
    279279ruleScopeName :: RuleParser String 
    280280ruleScopeName = choice . map symbol . map (map toLower) . map (tail . show) 
    281     $ [SState .. STemp] 
     281    $ [SState .. SOur] 
    282282 
    283283postSpace :: GenParser Char st a -> GenParser Char st a 
  • t/var/let.t

    r3016 r6432  
    3333 
    3434# Test that let() restores the variable at scope exit, not at subroutine 
    35 # entry. 
     35# entry.  (This might be a possibly bug.) 
    3636{ 
    3737  my $a     = 42; 
     
    4545  is $a, 23, "let() should not restore the variable, as our block exited succesfully (2)"; 
    4646} 
     47 
     48=pod 
     49 
     50Should these work? (They don't even parse currently.) 
     51 
     52{ 
     53  my @array = (0, 1, 2); 
     54  { 
     55    let @array[1] = 42; 
     56    is @array[1], 42, "let() changed our array element"; 
     57    0; 
     58  } 
     59  is @array[1], 1, "let() restored our array element"; 
     60} 
     61 
     62=cut 
  • t/var/temp.t

    r6356 r6432  
    3737  is $pkgvar, 42, "temp() restored the package variable (3-2)", :todo<bug>; 
    3838} 
     39 
     40=pod 
     41 
     42Should these work? (They don't even parse currently.) 
     43 
     44{ 
     45  my @array = (0, 1, 2); 
     46  { 
     47    temp @array[1] = 42; 
     48    is @array[1], 42, "temp() changed our array element"; 
     49  } 
     50  is @array[1], 1, "temp() restored our array element"; 
     51} 
     52 
     53=cut 
    3954 
    4055# Block TEMP{}