Changeset 5721

Show
Ignore:
Timestamp:
07/20/05 22:35:24 (3 years ago)
Author:
iblech
svk:copy_cache_prev:
7696
Message:

* Usual svn properties.
* "sub foo { try { return }; say 42 }" should return from &foo and not print

42, added a test for this bug to t/builtins/control_flow/try.t (FWIW, PIL2JS
behaves correctly :)).

* Pugs.Compile -- Emit &prefix:<*> for Syn "*" so I can implement *(...) in PIL2JS.
* PIL2JS: Fixed &die (but it's actually a bug in Pugs' Parser, will write a

test tomorrow).

* PIL2JS: New builtins: &Code::arity, &Array::push, &Array::shift, &try,

&statement_control:<for> (works with n-ary subs)

* Updated PIL2JS/README and added PIL2JS to pugs::hack.

Files:
8 modified

Legend:

Unmodified
Added
Removed
  • lib/pugs/hack.pod

    r5561 r5721  
    144144    |   |-- Code-Perl          Helper module for Perl 5 code generation 
    145145    |   |-- PIL-Run            PIL virtual machine in Perl 5 
     146    |   |-- PIL2JS             PIL to JavaScript compiler 
    146147    |   `-- Perl6-MetaModel    Perl 5 Prototype of the Perl 6 Metaclass model 
    147148    | 
  • perl5/PIL2JS/README

    r5700 r5721  
    1414  . 
    1515  |-- pil2js.pl           Frontend for the PIL:: modules 
     16  |-- runjs.pl            Compiles Perl 6 to JavaScript and runs it 
     17  |-- jspugs.pl           Interactive shell for PIL2JS development 
    1618  |-- lib 
    1719  |   |-- PIL 
     
    1921  |   |   `-- Nodes.pm    Module which provides appropriate ->as_js methods 
    2022  |   |                   for the objects returned by PIL::Parser 
     23  |-- lib6 
    2124  |   |-- Prelude 
    22   |   |   `-- JS.pm       JavaScript Prelude, written in Perl 6 
     25  |   |   `-- JS.pm       Part of the JavaScript Prelude, 
     26  |   |                   written in Perl 6 
     27  |-- libjs 
     28  |   `-- PIL2JS.js       Part of the JavaScript Prelude, 
     29  |                       written in JavaScript 
    2330 
    2431=head1 WHAT'S WORKING ALREADY? 
     
    2835=item * 
    2936 
    30 Variables (scalars and arrays) 
     37Variables (scalars, arrays, and hashes), assignment, binding 
    3138 
    3239=item * 
     
    9198function, e.g. C<@array[$idx] := $foo>. 
    9299 
     100=head2 Identity comparision 
     101 
     102The C<.uid> property which every C<PIL2JS.Box> object has got contains the 
     103unique ID of the box (or C<undefined> if it's a C<PIL2JS.Box.Constant>, as we 
     104can't map all real numbers and more to a finite C<.uid>). C<< &infix:<=:=> >> 
     105can then compare C<this.uid> with C<other.uid>. 
     106 
    93107=head2 Calling conventions 
    94108 
     
    100114extracted (see C<PIL::Nodes>, package C<PIL::Params>). 
    101115 
     116Additionally to the arguments passed by the user, the first argument is always 
     117a boxed C<PIL2JS.Context> object. Methods expect C<$?SELF> as their second 
     118argument. 
     119 
    102120=head2 Escape continuations 
    103121 
     
    107125    // normal body here... 
    108126  } catch(err) { 
    109     if(err instanceof PIL2JS.Exception.ret && this_sublevel >= err.level) { 
     127    if(err instanceof PIL2JS.ControlException.ret && this_sublevel >= err.level) { 
    110128      // The return/leave/whatever concerns us, return! 
    111129      return err.return_value; 
     
    119137C<&return> can then be simply implemented as: 
    120138 
    121   throw new PIL2JS.Exception.ret(sublevel_to_break_out_of, retval); 
     139  throw new PIL2JS.ControlException.ret(sublevel_to_break_out_of, retval); 
    122140 
    123 C<&last> is similar. 
     141C<&last> and C<&next> are similar. 
    124142 
    125143=head1 TODO 
     
    129147=item * 
    130148 
    131 Make C<use js:Foo> load C<Foo> from L<JSAN|http://www.openjsan.org/>? 
     149Make C<use js:Foo> load C<Foo> from L<JSAN|http://www.openjsan.org/> 
    132150 
    133151=item * 
    134152 
    135 Primitives 
    136  
    137 =item * 
    138  
    139 Better error reporting (with line number etc., should be relatively simple to 
    140 implement because of C<PPos>) 
    141  
    142 =back 
     153Primitives! 
    143154 
    144155=head1 AUTHOR 
    145156 
    146 Ingo Blechschmidt C<<iblech@web.de>> 
     157Ingo Blechschmidt C<< <iblech@web.de> >> 
    147158 
    148159=head1 LICENSE 
  • perl5/PIL2JS/lib/PIL/Nodes.pm

    r5717 r5721  
    3232} catch(err) { 
    3333  PIL2JS.call_chain.pop(); 
    34   if(err instanceof PIL2JS.Exception.ret && $level >= err.level) { 
     34  if(err instanceof PIL2JS.ControlException.ret && $level >= err.level) { 
    3535    return err.return_value; 
    3636  } else { 
     
    517517      PIL::Nodes::name_mangle($self->[0]), 
    518518      PIL::Nodes::doublequote($self->[0]); 
     519    $js .= sprintf 
     520      "%s.arity = %d;\n", 
     521      PIL::Nodes::name_mangle($self->[0]), 
     522      $self->[2]->arity; 
    519523 
    520524    # Special magic for methods. 
     
    554558 
    555559    # Sub declaration 
    556     return sprintf "new PIL2JS.Box.Constant(function (args) {\n%s\n})", 
     560    return sprintf "PIL2JS.Box.constant_func(%d, function (args) {\n%s\n})", 
     561      $self->[1]->arity, 
    557562      PIL::Nodes::add_indent 1, PIL::Nodes::generic_catch($IN_SUBLIKE, $body); 
    558563  } 
     
    570575 
    571576    local $_; 
    572     return sprintf "new PIL2JS.Box.Constant(function (args) { var cxt = args.shift(); return(%s); })", 
     577    return sprintf "PIL2JS.Box.constant_func(0, function (args) { var cxt = args.shift(); return(%s); })", 
    573578      $self->[0]->as_js; 
    574579  } 
     
    590595    my $js; 
    591596    $js .= "var cxt   = args.shift();\n"; 
     597    $js .= "args      = PIL2JS.possibly_flatten(args);\n"; 
    592598    $js .= "var pairs = PIL2JS.grep_for_pairs(args);\n"; 
    593599    $js .= $_->as_js1() . "\n" for @$self; 
     
    607613    return $js; 
    608614  } 
     615 
     616  sub arity { 
     617    local $_; 
     618    my $arity = 0; 
     619    $_->is_required and $arity++ for @{ $_[0] }; 
     620    return $arity; 
     621  } 
    609622} 
    610623 
    611624{ 
    612625  package PIL::MkTParam; 
     626 
     627  sub is_required { $_[0]->{tpParam}{isOptional}->isa("PIL::False") } 
    613628 
    614629  sub as_js1 { 
  • perl5/PIL2JS/lib6/Prelude/JS.pm

    r5717 r5721  
    3030            body(); 
    3131          } catch(err) { 
    32             if(err instanceof PIL2JS.Exception.next) { 
     32            if(err instanceof PIL2JS.ControlException.next) { 
    3333              // Ok; 
    3434            } else { 
     
    3838        } 
    3939      } catch(err) { 
    40         if(err instanceof PIL2JS.Exception.last) { 
     40        if(err instanceof PIL2JS.ControlException.last) { 
    4141          return undefined; 
    4242        } else { 
     
    4949} 
    5050 
    51 sub JS::Root::last() is primitive { JS::inline "throw(new PIL2JS.Exception.last())"; 1 } 
    52 sub JS::Root::next() is primitive { JS::inline "throw(new PIL2JS.Exception.next())"; 1 } 
     51sub JS::Root::last() is primitive { JS::inline "throw(new PIL2JS.ControlException.last())"; 1 } 
     52sub JS::Root::next() is primitive { JS::inline "throw(new PIL2JS.ControlException.next())"; 1 } 
    5353 
    5454sub statement_control:<while>(Code $cond, Code $body) is primitive { 
     
    8888} 
    8989 
     90sub statement_control:<for>(@array is copy, Code $code) is primitive { 
     91  my $arity = $code.arity; 
     92  die "Can't use 0-ary subroutine as \"for\" body!" if $arity == 0; 
     93 
     94  while(+@array > 0) { 
     95    my @args = (); 
     96    my $i; loop $i = 0; $i < $arity; $i++ { 
     97      push @args: @array.shift; 
     98    } 
     99    $code(*@args); 
     100  } 
     101  undef; 
     102} 
     103 
    90104sub JS::Root::defined($a) is primitive { 
    91105  JS::inline(' 
     
    100114} 
    101115 
     116sub JS::Root::try(Code $code) is primitive { 
     117  JS::inline('new PIL2JS.Box.Constant(function (args) { 
     118    var cxt = args[0], code = args[1]; 
     119    var ret = new PIL2JS.Box.Constant(undefined); 
     120    try { ret = code.GET()([PIL2JS.Context.ItemAny]) } catch(err) { 
     121      if(err instanceof PIL2JS.ControlException.ret) { 
     122        throw err; 
     123      } else { 
     124        _24main_3a_3a_21.STORE(new PIL2JS.Box.Constant(err.toString())); 
     125        return new PIL2JS.Box.Constant(undefined); 
     126      } 
     127    } 
     128    return ret; 
     129  })')($code); 
     130} 
     131 
     132method JS::Root::shift(Array $self:) { 
     133  JS::inline('new PIL2JS.Box.Constant(function (args) { 
     134    var ret = args[1].GET().shift(); 
     135    return ret == undefined ? new PIL2JS.Box.Constant(undefined) : ret; 
     136  })')($self); 
     137} 
     138 
     139method JS::Root::push(Array $self: *@things) { 
     140  JS::inline('new PIL2JS.Box.Constant(function (args) { 
     141    var array = args[1].GET(), add = args[2].GET(); 
     142    for(var i = 0; i < add.length; i++) { 
     143      array.push(add[i]); 
     144    } 
     145    return new PIL2JS.Box.Constant(array.length); 
     146  })')($self, @things); 
     147} 
     148 
    102149method JS::Root::join(Array $self: Str $sep) { 
    103150  JS::inline(' 
     
    106153    } 
    107154  ')($self, $sep); 
     155} 
     156 
     157method JS::Root::arity(Code $self:) { 
     158  JS::inline('new PIL2JS.Box.Constant(function (args) { 
     159    return new PIL2JS.Box.Constant(args[1].GET().pil2js_arity); 
     160  })')($self); 
    108161} 
    109162 
     
    358411} 
    359412 
    360 sub infix:<=:=>($a is rw, $b is rw) is primitive { JS::inline('new PIL2JS.Box.Constant( 
     413sub infix:<=:=>($a, $b) is primitive { JS::inline('new PIL2JS.Box.Constant( 
    361414  function (args) { 
    362415    var cxt = args.shift(); 
     
    401454 
    402455sub JS::Root::warn(Str *@msg) is primitive { $JS::PIL2JS.warn(@msg.join("")) } 
    403 sub JS::Root::die(Str *@msg)  is primitive { $JS::PIL2JS.die.(@msg.join("")) } 
     456sub JS::Root::die(Str *@msg)  is primitive { $JS::PIL2JS.die(@msg.join("")) } 
    404457 
    405458sub infix:«=>»($key, $value)  is primitive { 
     
    411464  })')($key, $value); 
    412465} 
     466 
     467sub prefix:<*>(*@args) is primitive { 
     468  JS::inline('new PIL2JS.Box.Constant(function (args) { 
     469    var array = args[1]; 
     470    array.GET().flatten_me = true; 
     471    return array; 
     472  })')(@args); 
     473} 
  • perl5/PIL2JS/libjs/PIL2JS.js

    r5717 r5721  
    132132PIL2JS.Box.Stub.prototype     = PIL2JS.Box.prototype; 
    133133 
     134PIL2JS.Box.constant_func = function (arity, f) { 
     135  f.pil2js_arity = arity; 
     136  return new PIL2JS.Box.Constant(f); 
     137}; 
     138 
    134139// Call (possibly native sub) sub with args 
    135140PIL2JS.call = function (inv, sub, args) { 
     
    184189}; 
    185190 
    186 // Magical variable: $?POSITION. 
     191// Magical variables: $?POSITION and $!. 
    187192var _24main_3a_3a_3fPOSITION = new PIL2JS.Box("<unknown>"); 
     193var _24main_3a_3a_21         = new PIL2JS.Box(undefined); 
    188194 
    189195// Prettyprint an error msg. 
     
    205211// &return, &leave, &last, &next are all implemented using faked escape 
    206212// continuations, i.e. exceptions. 
    207 PIL2JS.Exception = {}; 
    208 PIL2JS.Exception.last  = function () {}; 
    209 PIL2JS.Exception.next  = function () {}; 
    210 PIL2JS.Exception.ret   = function (level, retval) { 
     213PIL2JS.ControlException      = {}; 
     214PIL2JS.ControlException.last  = function () {}; 
     215PIL2JS.ControlException.next  = function () {}; 
     216PIL2JS.ControlException.ret   = function (level, retval) { 
    211217  // The sublevel (SUBROUTINE, SUBBLOCK, etc.) the &return/&leave/whatever is 
    212218  // destined to. 
     
    239245        args.length == 1 ? args[0] : 
    240246        new PIL2JS.Box.Constant(undefined); 
    241       throw(new PIL2JS.Exception.ret(level, ret)); 
     247      throw(new PIL2JS.ControlException.ret(level, ret)); 
    242248    }); 
    243249  }); 
     
    260266 
    261267  return pairs; 
     268}; 
     269 
     270// *@foo sets @foo's .flatten_me property to true. 
     271// Here, we expand these flattened arrays. 
     272PIL2JS.possibly_flatten = function (args) { 
     273  var ret = []; 
     274 
     275  for(var i = 0; i < args.length; i++) { 
     276    if(args[i].GET() instanceof Array && args[i].GET().flatten_me) { 
     277      ret = ret.concat(args[i].GET()); 
     278    } else { 
     279      ret.push(args[i]); 
     280    } 
     281  } 
     282 
     283  return ret; 
    262284}; 
    263285 
  • perl5/Perl6-MetaModel/t/80_Code.t

    • Property svn:mime-type set to text/plain; charset=UTF-8
    • Property svn:eol-style set to native
  • src/Pugs/Compile.hs

    r5697 r5721  
    359359    compile (Syn "\\{}" exps) = do 
    360360        compile (App (Var "&circumfix:{}") Nothing exps) 
     361    compile (Syn "*" exps) = do 
     362        compile (App (Var "&prefix:*") Nothing exps) 
    361363    compile (Syn "=" [lhs, rhs]) = do 
    362364        lhsC <- enterLValue $ compile lhs 
  • t/builtins/control_flow/try.t

    r4635 r5721  
    44use Test; 
    55 
    6 plan 9; 
     6plan 11; 
    77 
    88{ 
     
    8787        is(eval('ref($!)'), "Dandy", ".. of the right class", :todo); 
    8888}; 
     89 
     90{ 
     91        my $was_in_foo; 
     92        sub foo { 
     93                $was_in_foo++; 
     94                try { return 42 }; 
     95                $was_in_foo++; 
     96                return 23; 
     97        } 
     98        is foo(), 42,      'return() inside try{}-blocks works (1)', :todo<bug>; 
     99        is $was_in_foo, 1, 'return() inside try{}-blocks works (2)', :todo<bug>; 
     100}