package Prelude::JS; use warnings; use strict; { our %macro; sub register { $macro{$_[0]} = PIL::P5Macro::JS->new($_[0] => $_[1]) } } { register "&statement_control:if" => my $if = sub { my ($cc, $cond, $true, $false) = @_; return < sub { my ($cc, $cond, $true, $false) = @_; return $if->($cc, $cond, $false, $true); }; } { foreach my $name (qw) { register "&$name" => sub { my ($cc) = @_; # We purposefully *don't* include the cc. # Think "next; $other_code" -- $other_code has *no* possibility of being # called. (This does not affect "next if ...; $other_code".) return "(function () { throw new PIL2JS.ControlException.$name })()"; }; } } { register "&Class::_create" => sub { my ($cc, $classname) = @_; # Total hack. $classname =~ s/^.*?new PIL2JS.Box.Constant\((".*")\)$/eval $1/eg or die; push @PIL::PIL1_HACK_CLASSDECLS, sprintf "if(!%s) var %s = PIL2JS.new_empty_class(%s, _3aMain_3a_3aItem);", PIL::name_mangle(":$classname"), PIL::name_mangle(":$classname"), PIL::doublequote($classname); return "$cc(new PIL2JS.Box.Constant(undefined))"; }; } # Standard operators, taken from (v6) Prelude::JS::Operators { my @subs = ( [ "infix:<", "N", "Number(a) < Number(b)" ], [ "infix:>", "N", "Number(a) > Number(b)" ], [ "infix:<=", "N", "Number(a) <= Number(b)" ], [ "infix:>=", "N", "Number(a) >= Number(b)" ], [ "infix:==", "N", "Number(a) == Number(b)" ], [ "infix:!=", "N", "Number(a) != Number(b)" ], [ "infix:lt", "S", "String(a) < String(b)" ], [ "infix:gt", "S", "String(a) > String(b)" ], [ "infix:le", "S", "String(a) <= String(b)" ], [ "infix:ge", "S", "String(a) >= String(b)" ], [ "infix:eq", "S", "String(a) == String(b)" ], [ "infix:ne", "S", "String(a) != String(b)" ], [ "infix:+", "N", "Number(a) + Number(b)" ], [ "infix:-", "N", "Number(a) - Number(b)" ], [ "infix:*", "N", "Number(a) * Number(b)" ], [ "infix:/", "N", "Number(b) == 0 ? eval('throw(new Error(\\'Division by zero\\'))') : Number(a) / Number(b)" ], [ "infix:%", "N", "Number(b) == 0 ? eval('throw(new Error(\\'Modulo zero\\'))') : Number(a) % Number(b)" ], [ "infix:**", "N", "Math.pow(Number(a), Number(b))" ], ); for (@subs) { my ($name, $type, $body) = @$_; my $undef = $type eq "S" ? '""' : 0; my $conv = "_26Main_3a_3aprefix_3a_" . ($type eq "S" ? "7e" : "2b"); register "&$name" => sub { my ($cc, $a, $b) = @_; my %param = (a => $a, b => $b); my $jsbody = $body; $jsbody =~ s/\b([ab])\b/PIL2JS.cps2normal($conv.FETCH(), [PIL2JS.Context.ItemAny, $1]).toNative()/g; # Previously, "|| $undef" was required, This is no longer the case, as # &prefix:<[+~]> always return 0 or "" on undefined. # "Why not simply make +undef return undef?" -- Because then all # operations yield NaN, which doesn't match Perl's semantics. return "PIL2JS.possibly_autothread([$a, $b], [true, true], $cc, function (__cc, a, b) { __cc(new PIL2JS.Box.Constant($jsbody)) })"; }; } } 1;