Changeset 5697

Show
Ignore:
Timestamp:
07/19/05 16:28:50 (3 years ago)
Author:
iblech
svk:copy_cache_prev:
7696
Message:

* Pugs.Compile -- Added a comment explaining why the raw Exp of a PPos isn't showed.
* PIL2JS: Moved the JS part of the Prelude to libjs/PIL2JS.js.
* PIL2JS: pil2js.pl, jspugs.pl -- Sanitized options.
* PIL2JS: PIL2JS.js, Prelude::JS -- Fixed linefeeds not working correctly undef

IE, thanks to Arathorn++ and castaway++.

Files:
2 added
4 modified

Legend:

Unmodified
Added
Removed
  • perl5/PIL2JS/jspugs.pl

    r5667 r5697  
    9898  my $pil = pugs("-I$cfg{lib6}", "-CPIL", "-MPrelude::JS", "-e", "''"); 
    9999  print $OUT "Error: Couldn't compile Prelude::JS to PIL!\n" and return if not defined $pil; 
    100   pil2js($pil, $cfg{preludepc}, "--no-jsprelude") or 
     100  pil2js($pil, $cfg{preludepc}, "--jsprelude-mode=no", "--p6preludepc-mode=no") or 
    101101    print $OUT "Error: Couldn't compile Prelude::JS to JavaScript!\n"; 
    102102  command_conf("preludepc"); 
     
    134134  my $pil = pugs("-I$cfg{lib6}", "-CPIL", @_); 
    135135  print $OUT "Error: Couldn't compile to PIL!\n" and return if not defined $pil; 
    136   pil2js($pil, $cfg{output}, "--html", "--preludepc", $cfg{preludepc}) or 
     136  pil2js($pil, $cfg{output}, "--html", "--p6preludepc-path", $cfg{preludepc}) or 
    137137    print $OUT "Error: Couldn't compile to JavaScript!\n" and return; 
    138138  command_conf("output"); 
     
    142142  my $pil = pugs("-I$cfg{lib6}", "-CPIL", "-e", $_[0]); 
    143143  print $OUT "Error: Couldn't compile to PIL!\n" and return if not defined $pil; 
    144   pil2js($pil, undef, "--no-jsprelude") or 
     144  pil2js($pil, undef, "--jsprelude-mode=no", "--p6preludepc-mode=no") or 
    145145    print $OUT "Error: Couldn't compile to JavaScript!\n" and return; 
    146146  print $OUT "\n"; 
  • perl5/PIL2JS/lib6/Prelude/JS.pm

    r5690 r5697  
    142142  JS::inline(' 
    143143    function (msg) { 
    144       // Convert "\n"s correctly (IE...) 
    145       var LF = typeof document != "undefined" && typeof document.all != "undefined" 
    146         ? "\r" 
    147         : "\n"; 
    148       msg.replace(/\n/, LF); 
    149  
    150144      // Rest copied from 
    151145      // http://openjsan.org/doc/t/th/theory/Test/Simple/0.11/lib/Test/Builder.html. 
  • perl5/PIL2JS/pil2js.pl

    r5690 r5697  
    1111use PIL::Nodes; 
    1212 
     13local ($/, $_); 
     14 
     15sub slurp($) { 
     16  open my $fh, "<", $_[0] or die "Couldn't open \"$_[0]\" for reading: $!\n"; 
     17  local $/; 
     18  return <$fh>; 
     19} 
     20 
     21sub guess_jsprelude_path { 
     22  my $pathsep = $^O eq "MSWin32" ? "\\" : "/"; 
     23 
     24  my $path =  $INC{"PIL${pathsep}Nodes.pm"}; 
     25  $path    =~ s[PIL${pathsep}Nodes\.pm][..${pathsep}libjs${pathsep}PIL2JS.js]; 
     26 
     27  return -f $path ? $path : undef; 
     28} 
     29 
     30my %jsprelude = (mode => "inline", path => guess_jsprelude_path()); 
     31my %p6prelude = (mode => "link"); 
     32 
    1333GetOptions( 
    14   "verbose"      => \my $verbose, 
    15   "html"         => \my $html, 
    16   "no-jsprelude" => \my $no_jsprelude, 
    17   "preludepc=s"  => \my $preludepc, 
    18   "yaml-dump"    => \my $yaml_dump, 
    19   "help"         => \&usage, 
     34  "verbose"            => \my $verbose, 
     35  "html"               => \my $html, 
     36  "jsprelude-mode=s"   => \$jsprelude{mode}, 
     37  "p6preludepc-mode=s" => \$p6prelude{mode}, 
     38  "jsprelude-path=s"   => \$jsprelude{path}, 
     39  "p6preludepc-path=s" => \$p6prelude{path}, 
     40  "yaml-dump"          => \my $yaml_dump, 
     41  "help"               => \&usage, 
    2042) or usage(); 
    2143 
    22 die "Option --preludepc needs --html.\n" 
    23   if $preludepc and not $html; 
    24 die <<ERR if $yaml_dump and ($html or $no_jsprelude or $preludepc); 
    25 Option --yaml-dump only dumps the PIL parse tree as YAML and then 
    26 exits; Terefore, it can't be used in conjunction with --html, 
    27 --no-jsprelude, or --preludepc. 
     44usage() unless 
     45  $jsprelude{mode} =~ /^(?:no|inline|link)$/ and 
     46  $p6prelude{mode} =~ /^(?:no|inline|link)$/; 
     47 
     48die <<ERR if not $html and ($jsprelude{mode} eq "link" or $p6prelude{mode} eq "link"); 
     49*** Can't link to Prelude if --html option not given! 
    2850ERR 
    2951 
    30 local $/; 
     52die <<ERR if not $p6prelude{path} and ($p6prelude{inline} or $p6prelude{link}); 
     53*** Can't inline or link to the precompiled Prelude, 
     54    as no path to the Prelude was given. 
     55ERR 
     56 
     57die <<ERR if not $jsprelude{path} and ($jsprelude{inline} or $jsprelude{link}); 
     58*** Can't inline or link to the JavaScript Prelude (PIL2JS.js), 
     59    as no path to the Prelude was given. 
     60ERR 
     61 
     62warn "*** Reading PIL...\n" if $verbose; 
     63 
    3164my $pil  = <>; 
    3265my $tree = PIL::Parser->parse($pil); 
     
    3871} 
    3972 
    40 # This is the part of the JS Prelude which needs to be written in JS. 
    41 local $_; 
    42 my $prelude = <<'EOF'; 
    43 if(PIL2JS == undefined) var PIL2JS = {}; 
    44  
    45 // This is necessary to emulate pass by ref, needed for is rw and is ref. 
    46 PIL2JS.Box = function (value) { 
    47   this.GET   = function ()  { return value }; 
    48   this.STORE = function (n) { value = n.GET(); return n }; 
    49 }; 
    50  
    51 PIL2JS.Box.prototype = { 
    52   clone: function () { 
    53     return new PIL2JS.Box(this.GET()); 
    54   }, 
    55   toNative: function () { 
    56     var unboxed = this.GET(); 
    57     if(unboxed instanceof Array) { 
    58       var arr = []; 
    59       for(var i = 0; i < unboxed.length; i++) { 
    60         arr.push(unboxed[i].toNative()); 
    61       } 
    62       return arr; 
    63     } else if(unboxed instanceof Function) { 
    64       return function () { 
    65         var args = arguments; 
    66         for(var i = 0; i < args.length; i++) 
    67           args[i] = new PIL2JS.Box.Constant(args[i]); 
    68         return unboxed(args).toNative(); 
    69       }; 
    70     } else { 
    71       return unboxed; 
    72     } 
    73   }, 
    74   perl_methods: {} 
    75   /* 
    76     toString: function () { 
    77       _26main_3a_3aprefix_3a_7e.GET()([this]); 
    78     }, 
    79   */ 
    80 }; 
    81  
    82 PIL2JS.Box.ReadOnly = function (box) { 
    83   this.GET   = function ()  { return box.GET() }; 
    84   this.STORE = function (n) { PIL2JS.die("Can't modify constant item!\n"); return n }; 
    85 }; 
    86 PIL2JS.Box.Constant = function (value) { 
    87   this.GET   = function ()  { return value }; 
    88   this.STORE = function (n) { PIL2JS.die("Can't modify constant item!\n"); return n }; 
    89 }; 
    90 PIL2JS.Box.Stub = function (value) { 
    91   this.GET   = function ()  { PIL2JS.die(".GET() of a PIL2JS.Box.Stub called!\n") } 
    92   this.STORE = function (n) { PIL2JS.die(".STORE() of a PIL2JS.Box.Stub called!\n"); return n }; 
    93 }; 
    94  
    95 PIL2JS.Box.ReadOnly.prototype = PIL2JS.Box.prototype; 
    96 PIL2JS.Box.Constant.prototype = PIL2JS.Box.prototype; 
    97 PIL2JS.Box.Stub.prototype     = PIL2JS.Box.prototype; 
    98  
    99 // Call (possibly native sub) sub with args 
    100 PIL2JS.call = function (inv, sub, args) { 
    101   if(sub == undefined) 
    102     PIL2JS.die("Use of uninitialized value in subroutine entry!\n"); 
    103  
    104   // It's a plain sub (i.e. not method) call. 
    105   if(inv == undefined) { 
    106     // It's a boxed (and therefore Perl 6) sub. 
    107     if(sub.GET) { 
    108       var ret = sub.GET()(args); 
    109       if(ret == undefined) 
    110         PIL2JS.die("Internal error: Boxed sub returned unboxed undefined!"); 
    111       return ret; 
    112     } else { 
    113       var code = "new PIL2JS.Box.Constant(sub("; 
    114       for(var i = 0; i < args.length; i++) { 
    115         code += "args[" + i + "].toNative(),"; 
    116       } 
    117       if(args.length > 0) code = code.slice(0, -1); 
    118       code += "))"; 
    119       return eval(code); 
    120     } 
    121   } else { 
    122     if(inv.GET) { 
    123       if(inv.perl_methods[sub]) { 
    124         return PIL2JS.call(undefined, inv.perl_methods[sub], [inv].concat(args)); 
    125       } else { 
    126         PIL2JS.die("No such method: \"" + sub + "\""); 
    127       } 
    128     } else { 
    129       PIL2JS.die("Internal error: PIL2JS.call not implemented for invocation of native methods\n"); 
    130     } 
    131   } 
    132 }; 
    133  
    134 PIL2JS.make_slurpy_array = function (inp_arr) { 
    135   var out_arr = []; 
    136  
    137   for(var i = 0; i < inp_arr.length; i++) { 
    138     if(inp_arr[i].GET() instanceof Array) { 
    139       out_arr = out_arr.concat(inp_arr[i].GET()); 
    140     } else { 
    141       out_arr.push(inp_arr[i]); 
    142     } 
    143   } 
    144  
    145   return out_arr; 
    146 }; 
    147  
    148 _24main_3a_3a_3fPOSITION = new PIL2JS.Box("<unknown>"); 
    149  
    150 PIL2JS.new_error = function (msg) { 
    151   return new Error(msg.substr(-1, 1) == "\n" 
    152     ? msg 
    153     : msg + " at " + _24main_3a_3a_3fPOSITION.toNative() 
    154   ); 
    155 }; 
    156 PIL2JS.warn = function (msg) { alert(PIL2JS.new_error(msg)) }; 
    157 PIL2JS.die = function (msg) { 
    158   var error = PIL2JS.new_error(msg); 
     73warn "*** Compiling input PIL to JavaScript...\n" if $verbose; 
     74my $load_check = <<EOF; 
     75if(PIL2JS == undefined) { 
     76  var error = new Error("PIL2JS.js not loaded; aborting."); 
    15977  alert(error); 
    16078  throw(error); 
    161 }; 
    162  
    163 PIL2JS.Exception = {}; 
    164 PIL2JS.Exception.last  = function () {}; 
    165 PIL2JS.Exception.next  = function () {}; 
    166 PIL2JS.Exception.ret   = function (level, retval) { 
    167   this.level        = level; 
    168   this.return_value = retval; 
    169   this.toString     = function () { 
    170     var msg =  
    171       "Can't return outside a " + level + "-routine. at " + 
    172       _24main_3a_3a_3fPOSITION.toNative(); 
    173     alert(msg); 
    174     return msg; 
    175   } 
    176 }; 
    177  
    178 _26PIL2JS_3a_3aInternals_3a_3ageneric_return = 
    179   new PIL2JS.Box.Constant(function (args) { 
    180     var level = args[0].toNative(); 
    181     return new PIL2JS.Box.Constant(function (args) { 
    182       args = PIL2JS.make_slurpy_array(args); 
    183       var ret = 
    184         args.length >  1 ? new PIL2JS.Box.Constant(args) : 
    185         args.length == 1 ? args[0] : 
    186         new PIL2J2.Box.Constant(undefined); 
    187       throw(new PIL2JS.Exception.ret(level, ret)); 
    188     }); 
    189   }); 
    190  
    191 PIL2JS.Pair = function (key, value) { 
    192   this.key   = key; 
    193   this.value = value; 
    194 }; 
    195  
    196 PIL2JS.part_pairs = function (args) { 
    197   var normal_args = []; 
    198   var pairs       = {}; 
    199  
    200   for(var i = 0; i < args.length; i++) { 
    201     if(args[i].GET() instanceof PIL2JS.Pair) { 
    202       pairs[args[i].GET().key.toNative()] = args[i].GET().value; 
    203     } else { 
    204       normal_args.push(args[i]); 
    205     } 
    206   } 
    207  
    208   return [normal_args, pairs]; 
    209 }; 
     79} 
    21080EOF 
    21181 
    212 my $js = join "\n", map { $_->as_js } @{ $tree->{"pilGlob"} }, $tree->{pilMain}; 
     82my $program_js = join "\n", 
     83  $load_check, 
     84  map { $_->as_js } @{ $tree->{"pilGlob"} }, $tree->{pilMain}; 
     85 
     86warn "*** Inlining the JavaScript Prelude (PIL2JS.pl)...\n" if $verbose; 
     87my $jsprelude_js = $jsprelude{mode} eq "inline" ? slurp $jsprelude{path} : undef; 
     88warn "*** Inlining the Perl 6 Prelude...\n" if $verbose; 
     89my $p6prelude_js = $p6prelude{mode} eq "inline" ? slurp $p6prelude{path} : undef; 
     90 
     91my $js; 
     92$js .= $jsprelude_js if $jsprelude{mode} eq "inline" and not $html; 
     93$js .= $p6prelude_js if $p6prelude{mode} eq "inline"; 
     94$js .= $program_js; 
    21395 
    21496unless($html) { 
    215   print $prelude . "\n" unless $no_jsprelude; 
    21697  print $js; 
    21798} else { 
    21899  # Output a standard HTML skeleton. 
    219100  my $indent = sub { join "\n", map { " " x 6 . $_ } split "\n", shift }; 
    220   printf <<EOF, $no_jsprelude ? "" : $indent->($prelude), $indent->($js); 
     101  my $link   = sub { "<script type=\"text/javascript\" src=\"$_[0]\"></script>" }; 
     102 
     103  print <<EOF; 
    221104<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    222105  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
     
    229112    <pre id="__pil2js_tty"></pre> 
    230113 
    231     @{[ 
    232       $no_jsprelude 
    233         ? "" 
    234         : "<script type=\"text/javascript\">//<![CDATA[\n%s\n    //]]</script>\n" 
    235     ]} 
    236     @{[ 
    237       $preludepc 
    238         ? "<script type=\"text/javascript\" src=\"$preludepc\"></script>\n" 
    239         : "" 
    240     ]} 
     114EOF 
     115 
     116  print <<EOF if $jsprelude{mode} eq "inline"; 
    241117    <script type="text/javascript">//<![CDATA[ 
    242 %s 
     118@{[$indent->($jsprelude_js)]} 
     119      //]] 
     120    </script> 
     121EOF 
     122 
     123  print <<EOF; 
     124    @{[ $jsprelude{mode} eq "link" ? $link->($jsprelude{path}) : "" ]} 
     125    @{[ $p6prelude{mode} eq "link" ? $link->($p6prelude{path}) : "" ]} 
     126    <script type="text/javascript">//<![CDATA[ 
     127@{[$indent->($js)]} 
    243128      //]] 
    244129    </script> 
     
    253138 
    254139Available options (options may be abbreviated to uniqueness): 
    255   --verbose           Sets verboseness. 
    256   --html              Outputs the JavaScript packed in an HTML page. 
    257   --no-jsprelude      Omits the part of the Prelude written in JavaScript. 
    258   --preludepc=http://.../preludepc.js 
    259                       Sets the path to a precompiled Prelude. 
     140  --verbose               Be verbose. 
     141  --html                  Output the JavaScript packed in an HTML page. 
     142 
     143  --jsprelude-mode=no|inline|link 
     144  --p6preludepc-mode=no|inline|link 
     145                          Don't include, inline, or link to the specified part 
     146                          of the Prelude. 
     147 
     148  --jsprelude-path=... 
     149  --p6preludepc-path=... 
     150                          Sets the path to the specified part of the Prelude. 
     151 
     152  --yaml-dump             Only output the PIL as YAML; don't compile anything. 
    260153 
    261154Recommended usage: 
    262155  \$ cd perl5/PIL2JS 
    263156  \$ pugs -CPIL -Ilib6 -MPrelude::JS -we 'say 2 + 3' | \ 
    264     ./pil2js.pl --html > test.js 
     157    ./pil2js.pl --html --p6preludepc-mode=no > test.js 
    265158  # or (*much* faster) 
    266159  \$ pugs -CPIL -Ilib6 -MPrelude::JS -we '' | \ 
    267     ./pil2js.pl --no-jsprelude > preludepc.js 
     160    ./pil2js.pl --jsprelude-mode=no --p6preludepc-mode=no > preludepc.js 
    268161  \$ pugs -CPIL -we 'say 2 + 3' | \ 
    269     ./pil2js.pl --html --preludepc="http://.../preludepc.js" > test.js 
     162    ./pil2js.pl --html --p6preludepc="http://.../preludepc.js" > test.js 
    270163 
    271164USAGE 
  • src/Pugs/Compile.hs

    r5667 r5697  
    8989    show PNil = "PNil" 
    9090    show PNoop = "PNoop" 
     91    -- We don't show the raw Exp here to ease writing parsers for PIL (Exp 
     92    -- contains things like MkEnv, etc.). 
    9193    show (PPos x _ z) = "(PPos " ++ show x ++ " Noop " ++ show z ++ ")" 
    9294    show (PApp x y i z) = "(PApp " ++ show x ++ " " ++ show y ++ " " ++ show i ++ " " ++ show z ++ ")"